使用实体框架 CTP5 映射与旧数据库的关系
我在使用 Code First / Fluent API 将两个实体与实体框架 CTP5 映射在一起时遇到问题。该数据库是我们公司正在切换到的另一个应用程序(Exact MAX)的旧数据库,我正在编写一个供我自己使用的应用程序来管理我们仓库中的发货。旧数据库中不会保存任何内容,其中包括本文中提到的实体。
这些实体是 SalesOrder(只有一个地址)和 Address(可以有多个 SalesOrder)。我必须指定列名,这是问题之一。另一个是地址有两个键,一个客户 ID 和一个地址 ID,它们链接到 SalesOrder 中的匹配列。列名很丑陋:表 SO_Master 中的 CUSTID_27 和 SHPCDE_27 代表 SalesOrders,表 SHIPPING_MASTER 中的 CUSTID_24 和 SHPCDE_24 代表地址。
昨晚我最终放弃了。本文中的代码行来自 SalesOrder 的映射,最后两段代码用于映射 SalesOrder 和 Address。每个键都有一个映射,是我从 Google 搜索中拼凑而成的,但我什至不确定它应该作为两个单独的通道来完成。检索到的 Address 记录本身是可以的,但 SalesOrders 中的记录则不行。检索到的一个 SalesOrder 记录具有有效地址,但其余 SalesOrder 具有空地址。
this.ToTable("SO_Master");
this.HasKey(so => so.Id);
this.Property(so => so.OrderDate).HasColumnName("ORDDTE_27");
this.Property(so => so.Id).HasColumnName("ORDNUM_27");
// Maps Customers
this
.HasOptional(s => s.Customer)
.WithMany(c => c.SalesOrders)
.IsIndependent()
.Map(m => m.MapKey(c => c.Id, "CUSTID_27"));
// Maps Address
this
.HasOptional(s => s.Address)
.WithMany(a => a.SalesOrders)
.IsIndependent()
.Map(m => m.MapKey(a => a.CustomerId, "CUSTID_27"));
this
.HasOptional(s => s.Address)
.WithMany(a => a.SalesOrders)
.IsIndependent()
.Map(m => m.MapKey(a => a.Id, "SHPCDE_27"));
如果需要的话,使用数据注释我不会有任何问题。我可以使用 LINQ to SQL,但我想看看是否有使用它的解决方案。也许 EF 不是该数据库的最佳选择,但代码分离得足够好,我可以进行实验。我正在使用 Visual Studio Express 和 SQL Server Express 2008 R2,并且无法找到任何允许设计器使用的内容,因此这就是我使用 Code First 的原因。
感谢您花时间阅读这篇文章。
好的,我最终采纳了 Vulgarbinary 的建议,使用数据注释,并在需要的地方使用了外键属性。我仍然必须使用 Fluent API 将地址映射到客户。我不确定到底为什么。在没有 Fluent API 映射的情况下,地址记录不断返回空客户。我猜是因为地址中有两个键用于将地址与订单链接,但只有一个用于客户到地址映射。
this.HasRequired(a => a.Customer).WithMany().HasForeignKey(a => a.CustomerId);
我想我现在更好地理解了如何使用 Fluent API,但我显然需要阅读更多内容。我也许可以返回并将一些属性更改回流畅的线条,但对于我正在开发的应用程序来说,这并不值得。
I'm having trouble mapping two entities together with Entity Framework CTP5 using Code First / Fluent API. The database is an old one from another application (Exact MAX) that our company is switching to, and I'm writing an application for my own use to manage shipments in our warehouse. Nothing is saved to the older database, which includes the entities mentioned in this post.
The entities are SalesOrder, which has only one Address, and Address, which can have many SalesOrders. I have to specify the column names and that's one of the problems. The other is that the Address has two keys, a Customer ID and an Address ID that link to matching columns in the SalesOrder. The column names are hideous: CUSTID_27 and SHPCDE_27 in table SO_Master for the SalesOrders, CUSTID_24 and SHPCDE_24 in table SHIPPING_MASTER for the Addresses.
I eventually gave up late last night. The lines of code in this post are from the map for the SalesOrder and the last two pieces are for mapping the SalesOrder and Address. There's a mapping for each key which I scrapped together from Google searches, but I'm not even sure it should be done as two separate passes. The Address records retrieved are OK by themselves, but the ones in the SalesOrders are not. One retrieved SalesOrder record had a valid address but the rest of the SalesOrders had null addresses.
this.ToTable("SO_Master");
this.HasKey(so => so.Id);
this.Property(so => so.OrderDate).HasColumnName("ORDDTE_27");
this.Property(so => so.Id).HasColumnName("ORDNUM_27");
// Maps Customers
this
.HasOptional(s => s.Customer)
.WithMany(c => c.SalesOrders)
.IsIndependent()
.Map(m => m.MapKey(c => c.Id, "CUSTID_27"));
// Maps Address
this
.HasOptional(s => s.Address)
.WithMany(a => a.SalesOrders)
.IsIndependent()
.Map(m => m.MapKey(a => a.CustomerId, "CUSTID_27"));
this
.HasOptional(s => s.Address)
.WithMany(a => a.SalesOrders)
.IsIndependent()
.Map(m => m.MapKey(a => a.Id, "SHPCDE_27"));
I would have no problems using data annotations if needed. I could use LINQ to SQL instead but I'd like to see if there's a solution using this. Maybe EF isn't the best choice for this database, but the code is separated well enough that I can experiment. I'm using Visual Studio Express and SQL Server Express 2008 R2, and have not been able to find anything to allow the use of designers, so that's why I'm using Code First.
Thanks for taking the time to read this post.
OK, I ended up taking Vulgarbinary's suggestion to use Data Annotations, and just used ForeignKey attributes where they were needed. I still had to use the Fluent API to map the Address to the Customer. I'm not sure why exactly. The Address records kept coming back with empty customers without the Fluent API mapping. I guess because I have two keys in the Address for linking addresses with orders, but only one for the customer to address mapping.
this.HasRequired(a => a.Customer).WithMany().HasForeignKey(a => a.CustomerId);
I think I understand how to use the Fluent API a little better now, but I obviously need to read up more. I might be able to go back and change some attributes back to Fluent lines, but it's not really worth it for the application I'm working on.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
SalesOrder
到Address
将是一个this.References(x => x.Address)
并且您将有一个单独的字段code>AddressID
这样您就可以映射外键关联和列名称。在地址映射上,您将有:
this.WithMany(x => x.SalesOrders)
在您的实际 POCO 中,您将需要
SalesOrder 中的
POCO 用于FK
Address
和单个Address
POCO。因此,在 SalesOrder 类中:
在 Address 类中:
这应该可以为您完成。
如果我可能会问,为什么使用 Fluent 而不是注释?通过注释一目了然的视图以及每行代码的生产力比使用 Fluent 映射要好得多。
The
SalesOrder
toAddress
would be athis.References(x => x.Address)
and you would have a separate field for theAddressID
so you can map the foreign key association and column name.On the Address mapping you would have a:
this.WithMany(x => x.SalesOrders)
In your actual POCO you will need the
FK
in theSalesOrder
POCO forAddress
and a singleAddress
POCO.So in class SalesOrder:
In class Address:
That should do it for you.
If I might ask, why use Fluent over annotations? The at a glance view through annotations as well as productivity per line of code is much better than using the Fluent mapping.