保持封装,同时保持存储库,实体框架,代码优先

时间:2013-04-07 12:36:22

标签: c# entity-framework encapsulation

我有一种情况,我将尝试大大简化,其中对象上的方法应该创建不同类的新持久对象。如何在保持存储库无知和封装的同时执行此操作?

在这个例子中,我们有小部件和小部件容器。销售或购买小部件时,会创建WidgetEvent(在其他位置)并添加到容器的WidgetEvents列表中。我们总是可以通过总结WidgetEvents的集合来查询容器中的件数。有时,工人调用并说容器是空的,即使容器中仍然应该有一些小部件。在这种情况下,我们调用“SetComplete”方法创建一个最终的WidgetEvent来将容器清零。

public class TestContext : DbContext
{
    public DbSet<WidgetEvent> WidgetEvents { get; set; }
    public DbSet<WidgetContainer> WidgetContainers { get; set; }
}

public class WidgetEvent
{
    public int Id { get; set; }
    public int Amount {get;set;}
    public WidgetContainer Container {get;set;}
}

public class WidgetContainer 
{
    public int Id { get; set; }
    public virtual ICollection<WidgetEvent> WidgetEvents {get;set;}

    public int GetPiecesOnHand()
    {
        return WidgetEvents.Sum(a=> a.Amount);
    }

    public void SetComplete()
    {
        if (GetPiecesOnHand() != 0)
        {

            WidgetEvents.Add(new WidgetEvent() { Amount = -GetPiecesOnHand() });
        }
    }
}

在我看来,正确的封装将在类定义中保持此事件的创建。这使得阅读代码的人更容易理解。但是我也看到没有办法在没有向类中引入一些知识库知识的情况下使这个新的WidgetEvent持久化。

我该怎么做?您可以假设我在其他地方有WidgetEvents的工厂。如果你想知道,SaveChanges没有意识到已经创建了WidgetEvent。

编辑:返回 25 25 0 0 哪个是对的。我想这让我对赛道变化感到有些困惑,但很高兴知道这有效。我几天前做过这样的事情并认为它不起作用。

        using (var context = new TestContext())
        {
            WidgetContainer acontainer = new WidgetContainer();
            acontainer.WidgetEvents = new List<WidgetEvent>();
            context.WidgetContainers.Add(acontainer);
            acontainer.WidgetEvents.Add(new WidgetEvent() { Container = acontainer, Amount = 25 });
            Console.WriteLine(acontainer.GetPiecesOnHand());
            context.SaveChanges();
        }

        using (var context = new TestContext())
        {
            WidgetContainer acontainer = context.WidgetContainers.Find(1);
            Console.WriteLine(acontainer.GetPiecesOnHand());
            acontainer.SetComplete();
            Console.WriteLine(acontainer.GetPiecesOnHand());
            context.SaveChanges();
        }

        using (var context = new TestContext())
        {
            WidgetContainer acontainer = context.WidgetContainers.Find(1);
            Console.WriteLine(acontainer.GetPiecesOnHand());

        }

1 个答案:

答案 0 :(得分:0)

如果WidgetContainer附加到(=跟踪)Entity Framework上下文而不给类引用上下文(或存储库),它实际上应该有用。

例如像这样的代码......

var widgetContainer = context.WidgetContainers.Find(1);
// or:
// var widgetContainer = context.WidgetContainers.Create();
// widgetContainer.Id = 1;
// context.WidgetContainers.Attach(widgetContainer);

widgetContainer.SetComplete();
context.SaveChanges();

...应将新的WidgetEvent插入数据库,并与widgetContainer建立外键关系,因为EF更改跟踪会识别已添加到WidgetEvents的新事件调用SaveChanges时的集合。

重要的一点是widgetContainer必须附加到上下文才能调用 SetComplete