Reputation: 925
I'm working on a project involving a legacy database schema and I'm running into problems when trying to load a related entity with Entity Framework (v6). Here is a simplified example of the data model that is being used:
public partial class Product {
public virtual Delivery Delivery { get; set; }
public virtual string OrderNumber { get; set; }
public virtual int? VersionNumber { get; set; }
public virtual string SocialNumber { get; set; }
}
public partial class Delivery {
public virtual string OrderNumber { get; set; }
public virtual int? VersionNumber { get; set; }
public virtual string SocialNumber { get; set; }
}
What I'm trying to achieve is to include the related Delivery
when retrieving a list of Product
s with a given SocialNumber
. A Delivery
is related to a Product
when the following condition is satisfied: product.OrderNumber == delivery.OrderNumber && product.VersionNumber == delivery.OrderNumber && product.SocialNumber == delivery.SocialNumber
.
The easiest way to do this would be calling Include
. However, that seems impossible since EF states that product.Delivery
is not a valid navigation property. I've tried to get the wanted result by using a projection, but failed. I'd be thankful if anyone could explain the best EF/LINQ approach to get a list of Product
s (+ their related Delivery
) with a given SocialNumber
.
Update: I think I should elaborate some more.
The main issue is that I'm dealing with a legacy database that does not have explicit (composite) keys on every table. For example, the Delivery
and Product
classes are mapped to tables that don't have a primary key. Since EF needs a primary key, dummy keys are defined as follows:
dbModelBuilder.Entity<Product>().hasKey(pk => new { pk.OrderNumber });
The entity classes are generated by a code generator, so adding annotations there isn't the solution I'm looking for. I guess it should be possible to define these things via the DbModelBuilder, but I'm not sure how to go about it.
Update: Figured out a solution.
The following query functions as expected (only showing the LINQ-query that should provide pairs of Product and related Delivery):
from data in _dartz3Context.V_VOV_GBA_DATAs
join delivery in _dartz3Context.VOV_GBA_AANLEVERINGs
on new { Bsn = data.MunicipalBasicAdministrationSocialSecurityNumber, Version = data.VersionNumber, PolicyNumber = data.InsurancePolicyNumber }
equals new { Bsn = delivery.MunicipalBasicAdministrationSocialSecurityNumber, Version = delivery.VersionNumber, PolicyNumber = delivery.InsurancePolicyNumber }
where data.MunicipalBasicAdministrationSocialSecurityNumber == socialSecurityNumber
select new { Data = data, Delivery = delivery }
Upvotes: 3
Views: 2650
Reputation: 12304
You need to define a composite key on your entities using annotations or the fluent api:
public partial class Product {
[Key, Column(Order = 0)]
public virtual string OrderNumber { get; set; }
[Key, Column(Order = 1)]
public virtual int? VersionNumber { get; set; }
[Key, Column(Order = 2)]
public virtual string SocialNumber { get; set; }
}
public partial class Delivery {
[Key, Column(Order = 0), ForeignKey("Product")]
public virtual string OrderNumber { get; set; }
[Key, Column(Order = 1), ForeignKey("Product")]
public virtual int? VersionNumber { get; set; }
[Key, Column(Order = 2), ForeignKey("Product")]
public virtual string SocialNumber { get; set; }
}
Example http://www.codeproject.com/Articles/813912/Create-Primary-Key-using-Entity-Framework-Code-Fir
Fluent API Version:
// Composite primary key
modelBuilder.Entity<Product>().HasKey(d => new { d.OrderNumber, d.VersionNumber, d.SocialNumber });
// Composite foreign key
modelBuilder.Entity<Delivery>()
.HasRequired(c => c.Product)
.WithMany(d => d.Delivery)
.HasForeignKey(d => new { d.OrderNumber, d.VersionNumber, d.SocialNumber });
Upvotes: 1