我在 Tickets
和 Tags
之间建立了多对多关系,可以毫无问题地向票证添加标签。但是,我无法更新/删除票证中的标签。
测试
[TestMethod]
public void TagRepository_UpdateTicketWithTwoTagsToNone_TicketHasZeroTag()
{
// Arrange
var ticketId = new Guid("54E86203-71F9-E411-80E5-000C29193DF7");
var selectedTags = "";
using (var context = new TicketModelContext())
{
using (new TransactionScope())
{
var ticketToUpdate = context.Tickets.Include(t=>t.Tags).First(t => t.TicketId == ticketId);
Assert.AreEqual(0, ticketToUpdate.Tags.Count);
ticketToUpdate.Tags.Add(context.Tags.Find(new Guid("D1757675-A06C-4C1F-9DAD-03EE00BB1100")));
ticketToUpdate.Tags.Add(context.Tags.Find(new Guid("96C66A97-9C3E-4B15-BD70-A4C832EEDE8B")));
context.SaveChanges();
var setupTicket = context.Tickets.Single(t => t.TicketId == ticketId);
Assert.AreEqual(2, setupTicket.Tags.Count);
// Act
new TagRepository().UpdateTicketTags(ticketId, selectedTags);
// Assert
var updatedTeicket = context.Tickets.Include(t => t.Tags).First(t => t.TicketId == ticketId);
Assert.AreEqual(0, updatedTeicket.Tags.Count);
// HERE I EXPECT 0 BUT GET 2
}
}
}
存储库方法
public void UpdateTicketTags(Guid ticketId, string selectedTags)
{
var tags = new List<Tag>();
using (var context = new TicketModelContext())
{
if (!String.IsNullOrEmpty(selectedTags))
{
foreach (var selectedTag in selectedTags.Split(','))
{
tags.Add(context.Tags.Find(new Guid(selectedTag)));
}
}
var ticketToUpdateTags = context.Tickets.Find(ticketId);
context.Entry(ticketToUpdateTags).Collection(t => t.Tags).Load();
ticketToUpdateTags.Tags = tags; // I EXPECT TAGS TO BE EMPTY IN THIS TEST
context.SaveChanges();
}
}
命令输出的SQL context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
DELETE [dbo].[TagTickets]
WHERE (([Tag_TagId] = @0) AND ([Ticket_TicketId] = @1))
-- @0: '96c66a97-9c3e-4b15-bd70-a4c832eede8b' (Type = Guid)
-- @1: '54e86203-71f9-e411-80e5-000c29193df7' (Type = Guid)
-- Executing at 26/05/2015 13:16:39 +01:00
-- Completed in 24 ms with result: 1
DELETE [dbo].[TagTickets]
WHERE (([Tag_TagId] = @0) AND ([Ticket_TicketId] = @1))
-- @0: 'd1757675-a06c-4c1f-9dad-03ee00bb1100' (Type = Guid)
-- @1: '54e86203-71f9-e411-80e5-000c29193df7' (Type = Guid)
-- Executing at 26/05/2015 13:16:39 +01:00
-- Completed in 21 ms with result: 1
我花了数小时尝试使用不同测试的不同代码变体,结果都相同。任何帮助将不胜感激!
最佳答案
基本上,您的测试不工作的原因是因为 Entity Framework 中不同上下文发生的更改没有反射(reflect)出来。即使您使用了 TransactionScope,如果您在内部上下文中调用 SaveChanges()(发生在您的 UpdateTicketTags() 中),那么这些更改将不会反射(reflect)在外部上下文中。
我通常更喜欢将 Action 分解成更小的 block 而不是一个长的上下文,这样
- 它模拟真实世界的操作如何在您的应用程序中发生(例如,如果这是一个 ASP.NET MVC 应用程序,多个 Controller 正在处理多个请求,这些请求可能会或可能不会修改同一个表)和
它为我提供每个对象的最新信息。
[TestMethod] public void TagRepository_UpdateTicketWithTwoTagsToNone_TicketHasZeroTag() { // Arrange var ticketId = new Guid("54E86203-71F9-E411-80E5-000C29193DF7"); var selectedTags = ""; using (var context = new TicketModelContext()) { var ticketToUpdate = context.Tickets.Include(t=>t.Tags).First(t => t.TicketId == ticketId); Assert.AreEqual(0, ticketToUpdate.Tags.Count); ticketToUpdate.Tags.Add(context.Tags.Find(new Guid("D1757675-A06C-4C1F-9DAD-03EE00BB1100"))); ticketToUpdate.Tags.Add(context.Tags.Find(new Guid("96C66A97-9C3E-4B15-BD70-A4C832EEDE8B"))); context.SaveChanges(); var setupTicket = context.Tickets.Single(t => t.TicketId == ticketId); Assert.AreEqual(2, setupTicket.Tags.Count); } // Act new TagRepository().UpdateTicketTags(ticketId, selectedTags); using (var context = new TicketModelContext()) { // Assert var updatedTeicket = context.Tickets.Include(t => t.Tags).First(t => t.TicketId == ticketId); Assert.AreEqual(0, updatedTeicket.Tags.Count); } }
关于c# - 代码优先 Entity Framework 无法更新多对多相关实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30456876/