试图让arround“违反多重约束”。 / SaveChanges正在改变价值观

时间:2015-07-02 00:39:25

标签: c# entity-framework

我正试图克服“违反多重性约束”。错误。我创建了一个简单/人为的例子来证明这个问题。在此示例中,我有一个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();
    }
}    

0 个答案:

没有答案