Mapping Relationship with Legacy Database using Entity Framework CTP5

1k views Asked by At

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.

1

There are 1 answers

2
VulgarBinary On BEST ANSWER

The SalesOrder to Address would be a this.References(x => x.Address) and you would have a separate field for the AddressID 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 the SalesOrder POCO for Address and a single Address POCO.

So in class SalesOrder:

Address Address {get;set;} 
int AddressID {get;set;}

In class Address:

List<SalesOrder> SalesOrders {get;set;}

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.