1

I have an issue working with EntityFramework using Code First configuration. I have two tables :

+---------------+        +-------------+
|  T_CONTRACTS  |        |  T_PERSONS  |
|---------------|        |-------------|
|CONTRACT_ID    |        |PERSON_ID    |
|CUSTOMER_ID    |        |NAME         |
+---------------+        +-------------+

I want to have a single EF entity :

public class Contract
{
    public int ContractId { get; set; }
    public int CustomerId { get; set; }
    public string CustomerName { get; set; }

}

Now, I would like to map my two tables on my entity. I order to do that, I used EntityTypeConfiguration.

public class ContractConfiguration : EntityTypeConfiguration<Contract>
{
    public ContractConfiguration()
    {
        ToTable("T_CONTRACTS", "ASSUROL"); //table and schema ALWAYS in uppercase
        HasKey(c => c.ContractId);
        Property(c => c.ContractId).HasColumnName("CONTRACT_ID").IsRequired();
        Property(c => c.CustomerId).HasColumnName("CUSTOMER_ID").IsRequired();

        // TODO : WIP, no idea of what i am doing
        HasRequired(c => c.CustomerName).WithRequiredPrincipal().Map( ca => {
            ca.MapKey("PERSON_ID");
            ca.ToTable("T_PERSONS", "ASSUROL");

            //Property(c => c.CustomerName).HasColumnName("NAME");
        });

    }
}

And here come the crap, i dont know how to achieve the mapping.

-How to map a entity fields to two tables ?

-How to join two tables with different column name for the foreign key (Here CUSTOMER_ID and PERSON_ID) ?

Thanks a lot,

PS : I know we can do this by making two entities with data annotation. I would like to avoid data annotation (because of separation of concern) and I would like to keep a single entity.

romainvv
  • 13
  • 4

2 Answers2

0

First, your models don't look right. You (probably) want something like:

public class Contract
{
    public int ContractId { get; set; }
    public int PersonId { get; set; }
    public Person Customer { get; set; }  // Use a navigation property to relate
}

public class Person
{
    public int PersonId { get; set; }
    public string Name { get; set; }
    public ICollection<Contract> Contracts { get; set; }  // A person can have many contracts, no?
}

Now you can alter your fluent code to:

public class ContractConfiguration : EntityTypeConfiguration<Contract>
{
    public ContractConfiguration()
    {
        ToTable("T_CONTRACTS", "ASSUROL"); //table and schema ALWAYS in uppercase
        HasKey(c => c.ContractId);  // Redundant since ContractId is key via convention
        Property(c => c.ContractId).HasColumnName("CONTRACT_ID").IsRequired();
        Property(c => c.PersonId).HasColumnName("CUSTOMER_ID").IsRequired();

        // Configure the relationship although EF should pick this up by convention as well...
        HasRequired(c => c.Customer).WithMany(p => p.Contracts);

    }
}

Now you can pretty easily compose a query to "flatten" the relationship:

context.Contracts.Select(c => new {
       c.ContractId,
       CustomerId = c.PersonId,
       CustomerName = c.Person.Name }).ToList();

EDIT: Upon a reread, I see that what you might be after is table splitting, although the first approach is better IMO because it seems like you are trying to build a ViewModel into your entity model which is not the intent of table splitting. IAC, if you want it the fluent code would look similar to:

modelBuilder.Entity<Contract>() 
    .Map(m => 
    { 
        m.Properties(c => new { c.CustomerId, c.ContractId }); 
        m.ToTable("T_CONTRACTS"); 
    }) 
    .Map(m => 
    { 
        m.Properties(p => new { p.PersonID, p.Name }); 
        m.ToTable("T_PERSONS"); 
    });

https://msdn.microsoft.com/en-us/data/jj591617.aspx?f=255&MSPPError=-2147217396#2.7

Steve Greene
  • 12,029
  • 1
  • 33
  • 54
0

Thanks a lot, I found others posts thanks to the keyword "Entity Splitting" : Entity splitting when key column has different names? Entity framework map entity to multiple tables?

Here is my working configuration :

    public ContractConfiguration()
    {
        HasKey(c => c.CustomerId);
        Map(m =>
        {
            m.Property(c => c.ContractId).HasColumnName("CONTRACT_ID");
            m.Property(c => c.CustomerId).HasColumnName("CUSTOMER_ID");
            m.ToTable("T_CONTRACTS");
        });
        Map(m =>
        {
            m.Property(cust => cust.CustomerId).HasColumnName("PERSON_ID");
            m.Property(cust => cust.CustomerName).HasColumnName("NAME");
            m.ToTable("T_PERSONS");
        });
    }
Community
  • 1
  • 1
romainvv
  • 13
  • 4