在EF Core中使用带有继承的封装集合

时间:2017-09-20 08:57:16

标签: c# .net-core entity-framework-core

我正在使用EF Core 2.0,并希望封装集合,以便在添加到集合时能够运行业务逻辑。 (见https://blog.oneunicorn.com/2016/10/28/collection-navigation-properties-and-fields-in-ef-core-1-1/

当受保护的字段和公共getter属于同一类型时,这非常有用,但是我无法使用继承方案进行此操作。

我的代码大致如下:

public abstract class ItemBase
{
    protected readonly List<DetailBase> _details = new List<DetailBase>();

    protected void AddDetail(DetailBase detail)
    {
        _details.Add(detail);

        // shared business logic
    }
}

public abstract class DetailBase
{
    // ...
}

public class DetailA : DetailBase
{
    // ...
}

public class DetailB : DetailBase
{
    // ...
}

public class ItemA : ItemBase
{
    public IEnumerable<DetailA> Details => _details.Cast<DetailA>();
    public void AddDetail(DetailA detail)
    {
        base.AddDetail(detail);

        // specific business logic for A
    }
}

public class ItemB : ItemBase
{
    public IEnumerable<DetailB> Details => _details.Cast<DetailB>();
    public void AddDetail(DetailB detail)
    {
        base.AddDetail(detail);

        // specific business logic for B
    }
}

但这会引发以下异常:

InvalidOperationException: The type of navigation property 'Details' on the entity type 'ItemA' is '<CastIterator>d__34<DetailA>' which does not implement ICollection<DetailA>. Collection navigation properties must implement ICollection<> of the target type.

如何在我的派生类中正确转换集合,以便可以使用公共getter 详细信息来访问它?

现在我已经通过复制派生类中的受保护字段来解决它,但这并不像上面的代码那样干净。

public class ItemA : ItemBase
{
    protected readonly List<DetailA> _details = new List<DetailA>();
    public IEnumerable<DetailA> Details => _details;
    public void AddDetail(DetailA detail)
    {
        base.DoSharedLogicOnAdd(detail);

        // specific business logic for A
    }
}

0 个答案:

没有答案