0

我有以下实体

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Sections Sections { get; set; }
}

public class Section
{
    public int ID { get; set; }
    public string Name { get; set; }
}

public class Sections : List<Section>, ICollection<Section>
{ }

我添加了一个项目 ID 为 1 的新项目,但其中没有任何部分......

现在我想修改该项目并在其中添加新部分,为此,我在上下文中检索该项目并将其保存在另一个上下文中。在这里,我必须使用两个单独的上下文,因为不确定用户何时要更新对象。在那之前我不能保持上下文对象打开。

        Item fAp;
        using (var ctx = new MyContext())
        {
            fAp = ctx.Items.Include(a => a.Sections).Single(a => a.Id == 1);
        }

        using (var ctx2 = new MyContext())
        {
            var nsec = new Section()
            {
                ID = 1,
                Name = "App Sec...1"
            };

            fAp.Sections.Add(nsec);
            ctx2.Entry(fAp).State = EntityState.Modified;
            ctx2.SaveChanges();
        }

通过这样做,新的部分没有被添加到数据库中。然后我在调用 ctx2.SaveChanges() 之前修改了代码并添加了以下行。

            ctx2.Entry(nsec).State = EntityState.Added;

已成功保存。

现在,我的问题是我有非常复杂的数据层次结构,我的意思是 Section 类也有很多子导航属性,这些属性还有很多,等等。

跟踪所有此类属性并手动设置它们的状态将非常困难。在这种情况下如何更新数据?

还有一件事,我不会使用急切加载,我的意思是在检索 Item 对象时我不会使用“包含”。我将在需要时使用显式加载,最后想要更新对象。

有什么最好的建议吗?

4

2 回答 2

0

设置状态仅影响您传递给Entry调用的单个实体。使用新的上下文实例进行数据持久性后,您必须始终告知要保存的任何实体的 EF 状态。

在您的情况下,您需要执行以下任一操作:

ctx2.Items.Attach(fAp); // Now you informed context about existing entity
fAp.Sections.Add(nsec); // Now you told both context and your item that new section exists

或者这个(避免一些其他问题的首选解决方案):

fAp.Sections.Add(nsec); // Your item is not tracked by the new context yet
ctx2.Items.Add(fAp);     // Now context things that both item and section are new
ctx2.Entry(fAp).State = EntityState.Unchanged; // Make sure that item is not inserted again

或这个:

fAp.Sections.Add(nsec); // Your item is not tracked by the new context yet
ctx2.Items.Attach(fAp); // Now context things that both item and section are existing
ctx2.Entry(nsec).State = EntityState.Added; // Make sure that section is tracked as new 

跟踪所有此类属性并手动设置它们的状态将非常困难。在这种情况下如何更新数据?

您的代码正在执行这些更改,因此应该不会那么困难。您甚至可以IsDirty为每个实体添加一些附加属性,并将其用作帮助器来跟踪实体的状态。

于 2012-05-02T12:37:34.513 回答
0

更新的实体

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Sections Sections { get; set; }
    public OtherInfo Info { get; set; }
}
public class OtherInfo
{
    public Guid Id {get;set;}
    public string Description {get;set;}
}

在检索到 Item 对象后,用户可以修改任何内容。比如说上面给出的例子,用户只是插入一个新的 Section 并通过传递对象 Item 来调用 commit 方法。

存储库类中的提交方法

public void Commit(Item fAp)
{
    using (var ct = new MyContext())
    {
        bool isExist = ct.Item.Any(a => a.Id == fAp.Id);
        if (!isExist)
        {
           ct.Items.Add(fAp);
        }
        else
        {
           ct.Items.Attach(fAp);
           ct.Entry(fAp).State = EntityState.Modified;
        }
        ct.SaveChanges();
    }
}

在提交方法中,我不会知道用户对对象做了什么。在我的测试中,我添加了部分并调用了这个方法。因为,OtherInfo 没有被修改,它的抛出错误是说 OtherInfo 表的主键重复。

所以,为了让它工作,我必须改变所有实体的状态,比如

部分 - 添加; 其他信息 - 无变化;项目 - 无变化

由于结构有点复杂,因此看起来很难跟踪所有实体。

这种方法(提交方法)可以还是建议更好的解决方案?

于 2012-05-03T09:43:42.127 回答