我正试图克服“违反多重性约束”。错误。我创建了一个简单/人为的例子来证明这个问题。在此示例中,我有一个Task
,其中包含一组子任务,Task
可以是一个或多个Task
的子任务。我希望能够订购子任务。我对如何建立多对多关系以及跟踪订单的其他建议持开放态度。
有3个测试波纹管都有不同的问题。我发现最有趣的是第三个测试,其中创建OrderedTask
并且值是正确的,直到TaskId
的值在'context.SaveChanges()'
Git上的解决方案:https://github.com/jrswenson/OrderedManyToMany
public class Task
{
private ICollection<OrderedTask> subTasks;
public Task()
{
subTasks = new List<OrderedTask>();
}
public int Id { get; set; }
public string Description { get; set; }
public virtual User AssignedUser { get; set; }
public int? AssignedUserId { get; set; }
[InverseProperty("Parent")]
public virtual ICollection<OrderedTask> SubTasks
{
get { return subTasks; }
set { subTasks = value; }
}
}
public class OrderedTask
{
public virtual Task Parent { get; set; }
[Key, Column(Order = 1), ForeignKey("Parent")]
public int ParentId { get; set; }
public virtual Task Task { get; set; }
[Key, Column(Order = 2), ForeignKey("Task")]
public int TaskId { get; set; }
public int Order { get; set; }
}
在单元测试中:
[TestClass]
public class TaskTest
{
[TestMethod]
public void CreateTasks()
{
var context = new Context();
var task = context.Tasks.FirstOrDefault(i => i.Description == "Lev1") ?? new Task { Description = "Lev1" };
if (context.Tasks.Any(i => i.Id == task.Id) == false)
context.Tasks.Add(task);
var sub1 = context.Tasks.FirstOrDefault(i => i.Description == "Lev2-1") ?? new Task { Description = "Lev2-1" };
if (context.Tasks.Any(i => i.Id == sub1.Id) == false)
context.Tasks.Add(sub1);
context.SaveChanges();
}
//This will throw a "Multiplicity constraint violated" error
[TestMethod]
public void InsertSubTasks()
{
var context = new Context();
var task = context.Tasks.FirstOrDefault(i => i.Description == "Lev1");
Assert.IsNotNull(task);
var sub1 = context.Tasks.FirstOrDefault(i => i.Description == "Lev2-1");
Assert.IsNotNull(sub1);
if (task.SubTasks.Any(i => i.TaskId == sub1.Id) == false)
{
var ot = new OrderedTask { Parent = task, Task = sub1, Order = task.SubTasks.Count + 1 };
task.SubTasks.Add(ot);
}
context.SaveChanges();
}
//This doesn't throw an exception.
//The OrderedTask is added to the database and
//the table has the correct values.
//Unfortunately, if it this is ran a second time,
//task.SubTasks is empty and causes a duplicate key error.
[TestMethod]
public void InsertSubTasks2()
{
var context = new Context();
var task = context.Tasks.FirstOrDefault(i => i.Description == "Lev1");
Assert.IsNotNull(task);
var sub1 = context.Tasks.FirstOrDefault(i => i.Description == "Lev2-1");
Assert.IsNotNull(sub1);
if (task.SubTasks.Any(i => i.TaskId == sub1.Id) == false)
{
var ot = new OrderedTask { Parent = task, Task = sub1, Order = task.SubTasks.Count + 1 };
context.OrderedTasks.Add(ot);
}
context.SaveChanges();
}
//This doesn't throw an exception the first time, but does on the
//second time.
//The OrderedTask is created and has the correct values after it is
//added to task.SubTasks, but somewhere in context.SaveChanges the value
//for ParentId and TaskId are both set to the same value of ParentId. The
//second time the test is ran task.SubTasks has a value (unlike the test above)
//, but the values are not correct.
[TestMethod]
public void InsertSubTasks3()
{
var context = new Context();
var task = context.Tasks.FirstOrDefault(i => i.Description == "Lev1");
Assert.IsNotNull(task);
var sub1 = context.Tasks.FirstOrDefault(i => i.Description == "Lev2-1");
Assert.IsNotNull(sub1);
if (task.SubTasks.Any(i => i.TaskId == sub1.Id) == false)
{
var ot = new OrderedTask { Parent = task, Task = sub1, Order = task.SubTasks.Count + 1 };
context.OrderedTasks.Add(ot);
task.SubTasks.Add(ot);
}
context.SaveChanges();
}
}