简体   繁体   中英

Entity Framework Fluent API Mapping Issue

How can I configure relationships between three tables to get all related data?

I have the following models (and the same tables in database):

public class Client 
{
  public Guid ClientId { get; set; }
  public string FirstName { get; set; }

  public virtual ClientCard ClientCard { get; set; }
}

public class Card
{
  public Guid CardId { get; set; }
  public string Number { get; set; }

  public virtual ClientCard ClientCard { get; set; }
}

public class ClientCard
{
  public Guid ClientCardId { get; set; }
  public Guid CardId { get; set; }
  public Guid ClientId { get; set; }

  public virtual Client Client { get; set; }
  public virtual Card Card { get; set; }
}

And the following OnModelCreating method:

protected override void OnModelCreating(DbModelBuilder builder)
    {
        builder.Conventions.Remove<PluralizingTableNameConvention>();

        ...

        builder.Entity<ClientCard>()
            .HasKey(x => x.ClientCardId);

        builder.Entity<ClientCard>()
            .HasRequired(x => x.Client)
            .WithRequiredPrincipal(x => x.ClientCard);

        builder.Entity<ClientCard>()
            .HasRequired(x => x.Card)
            .WithRequiredPrincipal(x => x.ClientCard);

        base.OnModelCreating(builder);
    }

But the results return without related data. Why?

For your code please try something like:

public class Client 
{
  public Guid ClientId { get; set; }
  public string FirstName { get; set; }

  public virtual ICollection<ClientCard> ClientCard { get; set; }
}

public class Card
{
  public Guid CardId { get; set; }
  public string Number { get; set; }

  public virtual ICollection<ClientCard> ClientCard { get; set; }
}

public class ClientCard
{
  public Guid ClientCardId { get; set; }
  public Guid CardId { get; set; }
  public Guid ClientId { get; set; }

  public virtual Client Client { get; set; }
  public virtual Card Card { get; set; }
}

And mapping:

    builder.Entity<Client>()
           .HasKey(t => t.ClinetID);
    ....
    builder.Entity<Client>()
           .HasMany(a => a.ClientCard)
           .WithRequired(p => p.Client)
           .HasForeignKey(p => p.ClientID);

For Card

    ....
    builder.Entity<Card>()
           .HasMany(a => a.ClientCard)
           .WithRequired(p => p.Card)
           .HasForeignKey(p => p.CardID);

But I think the best way is to create a separate map-file for each entities

Now I am using the following models:

public class Client 
{
   public Guid ClientId { get; set; }
   public string FirstName { get; set; }

   public Guid? CardId { get; set; }
   public virtual Card Card { get; set; }
}

public class Card
{
   public Guid CardId { get; set; }
   public string Number { get; set; }

   //public virtual Client Client { get; set; }
}

and the following OnModelCreating method:

protected override void OnModelCreating(DbModelBuilder builder)
{
        builder.Conventions.Remove<PluralizingTableNameConvention>();

        ... 

        builder.Entity<Client>()
            .HasOptional(x => x.Card)
            //.WithOptionalPrincipal(x=> x.Client) 
            //or
            //.WithOptionalDependent(x=> x.Client)
            ;

        base.OnModelCreating(builder);
}

All clients return with related data(if exists). But if I want to get ralated data with Card object and uncomment public virtual Client Client { get; set; } public virtual Client Client { get; set; } public virtual Client Client { get; set; } and WithOptionalPrincipal/WithOptionalDependent I always get on of these SqlException: "invalid column name 'Client_ClientId'" (if WithOptionalPrincipal is used) OR "invalid column name 'Card_CardId'" (if WithOptionalDependent is used)

I finally found a solution for my case.

First, I have removed CardId from Client class. Second, I have changed my OnModelCreating method:

protected override void OnModelCreating(DbModelBuilder builder)
    {
        builder.Conventions.Remove<PluralizingTableNameConvention>();

        ...

        builder.Entity<Client>()
            .HasOptional(x => x.Card)
            .WithOptionalDependent(x => x.Client)
            .Map(x => x.MapKey("CardId"))
            .WillCascadeOnDelete(false);

        builder.Entity<Card>()
            .HasOptional(x => x.Client)
            .WithOptionalPrincipal(x => x.Card)
            .WillCascadeOnDelete(false);

        base.OnModelCreating(builder);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM