实体框架和继承

3

我使用数据库优先(DB first)的方法。

我有3个带有“Order”列(记录的客户顺序)的表。我想在我的.NET应用程序中创建类似的重新排序逻辑,所以我想使用基类进行操作。我已经创建了以下结构:

enter image description here

但是该项目无法编译,因为每个3个表都没有映射到“Order”列,而且我也找不到一种映射它的方式:

enter image description here

如何表示,“Order”列应该映射到父类的“Order”属性?

更新:

否则,我必须创建类似的方法:

public interface IOrder
{
    int Order { get; set; }
}

public partial class EscortDescription : IOrder
{
}

public partial class EscortGroup : IOrder
{

}

public partial class EscortItem : IOrder
{

}

    private async Task ReorderEscortAsync(Infrastructure.IOrder item1, Infrastructure.IOrder item2)
    {
        Random rnd = new Random();
        if (item1 == null)
            throw new ArgumentNullException("firstItem");

        if (item2 == null)
            throw new ArgumentNullException("secondItem");

        int tmpItem1Order = item1.Order;
        int tmpItem2Order = item2.Order;
        item1.Order = rnd.Next(int.MinValue, -1);
        item2.Order = rnd.Next(int.MinValue, -1);
        _db.SaveChanges();

        item1.Order = tmpItem2Order;
        item2.Order = tmpItem1Order;
        await _db.SaveChangesAsync();
    }

    public async Task EscortGroupItemUpAsync(int ItemID)
    {
        var firstItem = (from i in _db.EscortItems where i.ID == ItemID select i).FirstOrDefault();
        if (firstItem == null)
            throw new Domain.RecordNotFoundException<int>(ItemID, "ID", "EscortItems");
        var secondItem = (from i in _db.EscortItems where i.Order < firstItem.Order orderby i.Order descending select i).FirstOrDefault();

        if (secondItem != null)
            await ReorderEscortAsync(firstItem, secondItem);
        else
            throw new FirstRecordException();
    }

    public async Task EscortGroupItemDownAsync(int ItemID)
    {
        var secondItem = (from i in _db.EscortItems where i.ID == ItemID select i).FirstOrDefault();
        if (secondItem == null)
            throw new Domain.RecordNotFoundException<int>(ItemID, "ID", "EscortItems");
        var firstItem = (from i in _db.EscortItems where i.Order > secondItem.Order orderby i.Order ascending select i).FirstOrDefault();

        if (firstItem != null)
            await ReorderEscortAsync(firstItem, secondItem);
        else
            throw new LastRecordException();
    }

    public async Task EscortGroupUpAsync(int ItemID)
    {
        var firstItem = (from i in _db.EscortGroups where i.ID == ItemID select i).FirstOrDefault();
        if (firstItem == null)
            throw new Domain.RecordNotFoundException<int>(ItemID, "ID", "EscortGroups");
        var secondItem = (from i in _db.EscortGroups where i.Order < firstItem.Order orderby i.Order descending select i).FirstOrDefault();

        if (secondItem != null)
            await ReorderEscortAsync(firstItem, secondItem);
        else
            throw new FirstRecordException();
    }

    public async Task EscortGroupDownAsync(int ItemID)
    {
        var secondItem = (from i in _db.EscortGroups where i.ID == ItemID select i).FirstOrDefault();
        if (secondItem == null)
            throw new Domain.RecordNotFoundException<int>(ItemID, "ID", "EscortGroups");
        var firstItem = (from i in _db.EscortGroups where i.Order > secondItem.Order orderby i.Order ascending select i).FirstOrDefault();

        if (firstItem != null)
            await ReorderEscortAsync(firstItem, secondItem);
        else
            throw new LastRecordException();
    }

我希望有一种方法可以传递基类对象作为参数。

我觉得继承在这里不是正确的方法。如果Order在这个上下文中的意思是序列的顺序,那么我认为每个实体都应该有自己的Order属性。 - Mike B
我不想复制重新排序的逻辑。我想要一个方法来重新排序并传递基类而不是具体类。 - Oleg Sh
你把它搞得很复杂,其实可以简单一些。我猜这是可能的,但我甚至不建议你这样做,因为Entity Framework有时无法解析这样的逻辑。 - Antoine Pelletier
@AntoinePelletier,我已经更新了问题,请查看两个类似的方法。我想要一个方法并传递基类对象。当然,我可以创建一个接口并为这些实体类实现它。 - Oleg Sh
但是即使使用接口,我也无法重构EscortXXXDownAsync和EscortXXXUpAsync方法。 - Oleg Sh
1个回答

1
如果我理解正确,OrderBase 没有对应的表。这意味着这是一种具体类型映射(TPC)。此链接 显示使用代码优先,映射 TPC 并不难。
然而,数据库优先和 TPC 结合在一起并不容易。您必须编辑 EDMX 才能完成此操作。
我已经用两个类完成了此操作。目前,在 EDMX 的 CS 映射内容部分中,您会发现类似于这样的内容:
  <EntitySetMapping Name="OrderBases">
    <EntityTypeMapping TypeName="IsTypeOf(TPCModel.EcortGroup)">
      <MappingFragment StoreEntitySet="EcortGroup">
        <ScalarProperty Name="GroupName" ColumnName="GroupName" />
        <ScalarProperty Name="ID" ColumnName="ID" />
      </MappingFragment>
    </EntityTypeMapping>
    <EntityTypeMapping TypeName="IsTypeOf(TPCModel.EscortItem)">
      <MappingFragment StoreEntitySet="EscortItem">
        <ScalarProperty Name="Escort" ColumnName="Escort" />
        <ScalarProperty Name="EcortGroup_ID" ColumnName="EcortGroup_ID" />
        <ScalarProperty Name="ID" ColumnName="ID" />
      </MappingFragment>
    </EntityTypeMapping>
  </EntitySetMapping>

这里说明了哪些列被映射到哪些属性。正如您所见,Order被省略了。但是您可以手动添加它们,EF会很高兴,并且EDMX仍然可以在设计器中打开:
    <EntityTypeMapping TypeName="IsTypeOf(TPCModel.EcortGroup)">
      <MappingFragment StoreEntitySet="EcortGroup">
        <ScalarProperty Name="GroupName" ColumnName="GroupName" />
        <ScalarProperty Name="ID" ColumnName="ID" />
        <ScalarProperty Name="Order" ColumnName="Order" />
      </MappingFragment>
    </EntityTypeMapping>
    <EntityTypeMapping TypeName="IsTypeOf(TPCModel.EscortItem)">
      <MappingFragment StoreEntitySet="EscortItem">
        <ScalarProperty Name="Escort" ColumnName="Escort" />
        <ScalarProperty Name="EcortGroup_ID" ColumnName="EcortGroup_ID" />
        <ScalarProperty Name="ID" ColumnName="ID" />
        <ScalarProperty Name="Order" ColumnName="Order" />
      </MappingFragment>
    </EntityTypeMapping>

然而:当你从数据库更新模型时,修改将会消失。每次这样做时,你都需要再次添加它们。如果可以的话,我强烈建议你将代码移植到Code-First。


我需要基于数据库的实现。 - Oleg Sh
那么这就是你唯一的选择。我希望你明白这仍然是数据库优先,但需要一些帮助。 - Gert Arnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接