When I try to load child entity of parent entity it loads with default values. If i try to load explicitly it throws exception Multiplicity constraint violated. The role 'Association_Customer_Target' of the relationship 'CodeFirstNamespace.Association_Customer' has multiplicity 1 or 0..1. This exception is thrown while retrieving the child entities of a complex graph.
I have a graph Association which has a child entity Customer with a relationship of one to zero or one and has an Independent association.*Primary key* is shared. I'm using EF6. lazy loading is enabled.
public class Association
{
public virtual long Id { get; set; }
public virtual string ExternalId { get; set; }
public virtual int OrganizationId { get; set; }
public virtual AssociationType AssociationType { get; set; }
public virtual Customer Customer {get; set;}
public Association()
{
Customer = new Customer();
}
}
Customer class.
public class Customer
{
public virtual long Id { get; set; } //Shared primary key
public virtual ICollection<Item> Items {get; set;}
public virtual ICollection<Complaint> Complaints {get; set;}
public customer()
{
Items = new List<Item>();
Complaints = new List<Complaint>();
}
}
Mapping are Uni directional:
public class AssociationMapping:EntityTypeConfiguration<Association>
{
public AssociationMapping() : base()
{
HasKey(x => x.Id);
Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.ExternalId).IsRequired();
Property(x => x.OrganizationId).IsRequired();
Property(x => x.AssociationType);
HasOptional(x => x.Customer).WithRequired().WillCascadeOnDelete();
}
}
public class CustomerMapping : EntityTypeConfiguration<Customer>
{
public CustomerMapping ():base()
{
HasKey(x => x.Id);
Property(x => x.Id);
HasMany(x => x.Items)
.WithOptional()
.HasForeignKey(key => key.CustomerId)
.WillCascadeOnDelete();
HasMany(x => x.Complaints)
.WithOptional()
.HasForeignKey(key => key.CustomerId)
.WillCascadeOnDelete();
}
}
When I Load My association entity it loads perfectly but child entity Customer is loaded with default values when i try to load Customer explicitly it throws the exception.
var dbassociation = Single<Association>(x => x.OrganizationId== asso.organizationId && x.ExternalId == asso.ExternalId && x.AssociationType == asso.AssociationType);
dbassociation.Customer = Single<Customer>(x => x.id == dbassociation.id);
[Update: Single Method]
public TEntity Single<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>>criteria) {
return Context.Set<TEntity>().SingleOrDefault(criteria); }
For testing purpose I have tried to eager load by removing virtual on Customer property in association class and tried following but it throws same excepetion
Context.Configuration.LazyLoadingEnabled = false;
Context.Entry<Association>(dbassociation).Reference<Customer>(pa => pa.Customer).Load();
I have also tried which throws same exception
var dbassociation = Context.Set<Association>().Include("Customer").SingleOrDefault(x => x.OrganizationId== asso.organizationId && x.ExternalId == asso.ExternalId && x.AssociationType == asso.AssociationType);
Now I came to conclusion that though I use different methods for retrieving the exception is same. The problem is with mapping I guess. I appreciate your comments and suggestions.
Try to remove
Customer = new Customer();
from the Association
constructor. Instantiating navigation references is a source for known problems (in contrast to instantiating empty navigation collections which is fine). It is the reason why you get a Customer
with default values. I'm not sure if it also explains the exception, but I could imagine that when the Association
gets loaded and attached to the context together with the uninitialized Customer
created by the default constructor EF detects related entities with invalid keys: The Association
which has (I assume) a key value !=0
and the related Customer
with a key ==0
(because it never has been initialized to another value). However, in a shared primary key association the two key values must match. Because they don't, it might cause the exception (however an exception that doesn't really point very well to the root of the problem).
Just a guess.