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

发布于 2024-12-06 01:28:42 字数 1457 浏览 0 评论 0原文

我正在 EF 4.1 中迈出第一步。因为我使用的是 NHibenate,所以代码优先的方法在我看来是最好的方法。我在一对多(或多对一)关系的良好映射方面遇到问题。假设我有 2 个实体:

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

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

当我这样保留它时,生成数据库时出现错误 - 表中的键丢失。我发现我可以通过将键的名称更改为 ID(但这不符合我的命名约定)或添加 [Key] 注释来修复它。即使我添加此注释,表的名称仍然是错误的 - 就像类名称一样,但带有“s”。 所以我尝试使用 Fluent 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 的订单)。

I am having my first steps in EF 4.1. Because I was using NHibenate, the code first approach seems to me as the best one. I have problem with good mapping of one-to-many (or many-to-one) realtionship. Let's say I have 2 entities:

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

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

When I leave it like that, there is an error while generating database - keys in tables are missing. I figured out I can fix it by changing names of the keys to ID (but it's not OK with my naming convention) or by adding [Key] annotation. Even if I add this annotation, still the names of tables are wrong - just like classes names but with 's'.
So I tried to use fluent API - I made mappings. But if I set mappings just like here:

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");
    }
}

the relation betweene tables in database is doubled.
What is the proper way to do one-to-many relationship using code-first approach? Am I thinking in a good direction or is it a wrong approach?

EDIT

OK, I have done it in the way @Eranga showed, but there is still a problem. When I'm getting Client from database, its Orders property is null (but in database it has some Orders with Order.ClientID == Client.ClientID).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

平定天下 2024-12-13 01:28:42

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

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");
    }
}

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

You need to map both properties participating in the relationship. You need to add ClientID column to Orders table.

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");
    }
}

Configuring the relationship from one entity is sufficient.

梦开始←不甜 2024-12-13 01:28:42

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

如果您有这样的类:

class ClientModel
{
    int ClientId;
    string Name;
}

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

那么这将代表数据库中的两个表,它们“不会”通过以下方式相互连接外键(它们将通过 OrderModel 中的 ClientId 连接),您可以从数据库获取诸如“GetAllOrdersWithSomeClientId”和“GetTheClientNameForSomeClientId”之类的数据。但是,当您从数据库中删除 Client 时,就会出现问题。因为这样仍然会有一些 Orders 包含 ClientId,而该 Client 不再存在于 Client 表中,这会导致异常在你的数据库中。

虚拟列表需要 Orders; (在 ClientModel 中)和 virtual ClienModel Client; (在 OrderModel 中)来创建关系。表 ClientModelOrderModel 之间的外键。

有件事我仍然不确定。这是 OrderModel 中的 int ClientId;。我猜想它必须与 ClientModel 中的 ClientId 具有相同的名称,以便实体框架知道外键必须连接哪两个属性。如果有人可以详细解释这一点,那就太好了。

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

this.Configuration.ProxyCreationEnabled = false;
this.Configuration.LazyLoadingEnabled = false;

This may help (it helped me, when i couldn't figure out how this works):

If you would have the classes like this:

class ClientModel
{
    int ClientId;
    string Name;
}

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

Then this would represent 2 tables in your database which "wouldn't" be connected with each other via a foreign key (they would be connected via the ClientId in the OrderModel) and you could get data like "GetAllOrdersWithSomeClientId" and "GetTheClientNameForSomeClientId" from the database. BUT problems would arise when you would delete a Client from the database. Because then there would still be some Orders which would contain a ClientId which doesn't exist in the Client table anymore and that would lead to anomalies in your database.

The virtual List<OrderModel> Orders; (in the ClientModel) and virtual ClienModel Client; (in the OrderModel) are needed to create the relation aka. the foreign key between the tables ClientModel and OrderModel.

There is one thing about which i'm still not sure about. Which is the int ClientId; in the OrderModel. I guess that it has to have the same name as the ClientId in the ClientModel so that the entity framework knows which 2 attributes the foreign key has to connect. Would be nice if someone could explain this in detail.

Also, put this into your DbContext constructor if something souldn't work:

this.Configuration.ProxyCreationEnabled = false;
this.Configuration.LazyLoadingEnabled = false;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文