Entity Framework Code first foreign key mapping

code-first entity-framework

Question

I have 2 entities:

  • Claim (ID, other primirives, one more relation) - Claims table
  • ClaimDetail (ID, ClaimID, other primitives, relations) - ClaimDetails table

Mapping:

modelBuilder.Entity<Claim>()
                        .HasMany(x => x.ClaimDetails)
                        .WithRequired(x => x.Claim)
                        .HasForeignKey(x => x.ClaimID)

A generated query:

exec sp_executesql N'SELECT 
[Extent1].[ID] AS [ID], 
[Extent1].[ClaimID] AS [ClaimID], 
[Extent1].[UserID] AS [UserID], 
[Extent1].[ClaimTypeID] AS [ClaimTypeID], 
[Extent1].[PermissionID] AS [PermissionID], 
[Extent1].[StartDate] AS [StartDate], 
[Extent1].[EndDate] AS [EndDate], 
[Extent1].[Justification] AS [Justification], 
[Extent1].[Claim_ID] AS [Claim_ID]
FROM  [dbo].[ClaimDetails] AS [Extent1]
OUTER APPLY  (SELECT TOP (1) [Project1].[ClaimDetailStatusID] AS [ClaimDetailStatusID]
    FROM ( SELECT 
        [Extent2].[ClaimDetailStatusID] AS [ClaimDetailStatusID], 
        [Extent2].[CreatedOn] AS [CreatedOn]
        FROM [dbo].[ClaimDetailStatus] AS [Extent2]
        WHERE [Extent1].[ID] = [Extent2].[ClaimDetailID]
    )  AS [Project1]
    ORDER BY [Project1].[CreatedOn] DESC ) AS [Limit1]
WHERE ([Extent1].[UserID] = @p__linq__0) AND ( NOT ([Limit1].[ClaimDetailStatusID] IN (12,11,4,7,13,10)))',N'@p__linq__0 int',@p__linq__0=4106

If i left out the mapping then EF will generate another column called Claim_ID1. What is wrong with this? How should I define the relation?

EDIT

public class Claim
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    [Required]
    public int SenderID { get; set; }

    [NotMapped]
    public UserModel Sender { get; set; } //TODO:

    [Required]
    public DateTime Created { get; set; }

    public string Note { get; set; }
    [Required]
    public int BossID { get; set; }

    [NotMapped]
    public UserModel Boss { get; set; } //TODO:

    public virtual IList<ClaimDetail> ClaimDetails { get; set; }
    public virtual IList<UserClaim> UserClaims { get; set; }
}

public class BaseClaimItem
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }

    [Required]
    public int PermissionID { get; set; }

    [Required]
    public DateTime StartDate { get; set; }

    [Required]
    public DateTime EndDate { get; set; }

    public string Justification { get; set; }

    public virtual Permission Permission { get; set; }

    [NotMapped]
    public virtual UserModel Claimant { get; set; }
}


public class ClaimDetail : BaseClaimItem
{
    [Required]
    public virtual int ClaimID { get; set; }

    [Required]
    public int UserID {get;set;}

    [NotMapped]
    public override UserModel Claimant {get;set;}

    [Required, Range(1, 5)]
    public int ClaimTypeID { get; set; }

    public virtual Claim Claim { get; set; }
    public virtual IList<ClaimDetailStatus> ClaimDetailStatus { get; set; }
    public virtual IList<Task> Tasks { get; set; }
    public virtual IList<ClaimDetailApprovalStep> ClaimDetailApprovalSteps { get; set; }

    public virtual ClaimType ClaimType { get; set; }
}
1
1
5/12/2013 8:35:13 PM

Accepted Answer

One interface implementation is missing from above. In that interface there is a property which returns a Collection. The [NotMapped] attribute was missing now works the association.

1
5/28/2013 2:22:09 PM

Popular Answer

How about try something simple with Property mapping rather than Fluent API mapping;

public class Claim 
{
   [Key]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int ClaimId { get; set; }
   public string Name { get; set; }

   public virtual ICollection<ClaimDetail> ClaimDetails { get; set; }
}

public class ClaimDetail
{
   [Key]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int ClaimDetailId { get; set; }

   [ForeignKey("Claim"), DatabaseGenerated(DatabaseGeneratedOption.None)]
   public int ClaimId { get; set; }

   public string Detail { get; set; }

   public virtual Claim Claim { get; set; }
}

Fluent API Mapping should be;

modelBuilder.Entity<Claim>()
    .HasMany(c => c.ClaimDetail)
    .WithOptional()
    .Map(m => m.MapKey("ClaimId"));


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow