实体框架首先是一对多关系代码

时间:2011-09-21 13:40:46

标签: entity-framework one-to-many relationship

我在EF 4.1中迈出了第一步。因为我使用的是NHibenate,所以代码第一种方法在我看来是最好的方法。我对一对多(或多对一)实现的良好映射存在问题。假设我有两个实体:

class ClientModel
{
    int ClientID;
    string Name;
    virtual IList<OrderModel> Orders;
}

class OrderModel
{
    int OrderID;
    string Details;
    virtual ClienModel Client;
}

当我这样离开时,生成数据库时出错 - 表中的键丢失。我想通过将键的名称更改为ID(但是我的命名约定不合适)或添加[Key]注释,我可以解决它。即使我添加了这个注释,表格的名称仍然是错误的 - 就像类名,但是带有's'。 所以我尝试使用流畅的API - 我制作了映射。但是,如果我像这里一样设置映射:

class ClientMapping
{
    ClientMapping()
    {
        this.HasKey(e => e.ClientID).Property(e => e.ID).HasColumnName("ClientID");
        this.Property(e => e.Name).HasColumnName("Name");
        this.HasMany(e => e.Orders).WithOptional().Map(p => p.MapKey("OrderID")).WillCascadeOnDelete();
        this.ToTable("Clients");
    }
}

class OrderMapping
{
    OrderMapping()
    {
        this.HasKey(e => e.OrderID).Property(e => e.OrderID).HasColumnName("OrderID");
        this.Property(e => e.Details).HasColumnName("Details");
        this.HasRequired(e => e.Client).WithMany().Map(p=>p.MapKey("Client")).WillCascadeOnDelete(false);
        this.ToTable("Orders");
    }
}

数据库中表之间的关系加倍。 使用代码优先方法进行一对多关系的正确方法是什么?我是在朝着一个好方向思考,还是一个错误的方法?

修改

好的,我已经以 @Eranga 显示的方式完成了,但仍然存在问题。当我从数据库获取Client时,其Orders属性为null(但在数据库中,它有一些Order.ClientID == Client.ClientID的订单)。

2 个答案:

答案 0 :(得分:6)

您需要映射参与该关系的两个属性。您需要将ClientID列添加到订单表。

class ClientMapping
{
    ClientMapping()
    {
        this.HasKey(e => e.ClientID).Property(e => e.ID).HasColumnName("ClientID");
        this.Property(e => e.Name).HasColumnName("Name");

        this.HasMany(e => e.Orders).WithRequired(o => o.Client)
           .Map(p => p.MapKey("ClientID")).WillCascadeOnDelete();

        this.ToTable("Clients");
    }
}

class OrderMapping
{
    OrderMapping()
    {
        this.HasKey(e => e.OrderID).Property(e => e.OrderID).HasColumnName("OrderID");
        this.Property(e => e.Details).HasColumnName("Details");
        this.ToTable("Orders");
    }
}

从一个实体配置关系就足够了。

答案 1 :(得分:0)

这可能有所帮助(当我无法弄清楚它是如何工作时,它帮助了我):

如果你有这样的课程:

class ClientModel
{
    int ClientId;
    string Name;
}

class OrderModel
{
    int OrderId;
    string Details;
    int ClientId;
}

然后这将代表数据库中的2个表,这些表“不会”通过外键相互连接(它们将通过ClientId中的OrderModel连接)你可以从数据库中获取“GetAllOrdersWithSomeClientId”和“GetTheClientNameForSomeClientId”等数据。但是当您从数据库中删除Client时会出现问题。因为那时仍然会有一些Orders包含ClientIdClient表中不再存在virtual List<OrderModel> Orders;,这会导致数据库出现异常。

需要ClientModel(在virtual ClienModel Client;)和OrderModel(在ClientModel中)来创建关系aka。表OrderModelint ClientId;之间的外键。

有一件事我还不确定。哪个是OrderModel中的ClientId。我想它必须与ClientModel中的this.Configuration.ProxyCreationEnabled = false; this.Configuration.LazyLoadingEnabled = false; 具有相同的名称,以便实体框架知道外键必须连接哪两个属性。如果有人能够详细解释这一点,那就太好了。

另外,如果某些东西不起作用,请将它放入DbContext构造函数中:

{{1}}