0

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

在这个例子中,我们有小部件和小部件容器。出售或购买小部件时,会创建一个 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());

        }
4

1 回答 1

0

WidgetContainer如果它附加到(=跟踪)实体框架上下文而不给类一个对上下文(或存储库)的引用,它实际上应该工作。

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

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

于 2013-04-07T13:28:09.230 回答