2012-07-11 2 views
3

Я использую Entity Framework (версия 4.3.1) ПОКО с базой данных SQL Server 2012, и я эту схему данных ...Entity Framework POCO: как сопоставить связанные свойства с плоской таблицей?

Table2 
======  
Table2Id : int : Identity (1,1) Primary Key not null 
Name : nvarchar(10) not null 

Table1 
======  
Table1Id : int : Identity (1,1) Primary Key not null 
Name : nvarchar(10) not null 
Table2Id : int not null (foreign key to Table2) 

Root 
==== 
RootId : int : Identity (1,1) Primary Key not null 
Table1Id : int not null (foreign key to Table1) 
Table2Id : int not null (foreign key to Table2) 

Ничего предосудительного там кроме Теперь самое интересное заключается в том, что я делаю не хотите иметь свойство на моем объекте Root для Table2, вместо этого я хочу, чтобы этот идентификатор был заполнен из соответствующей таблицы2 из таблицы1.

Чтобы объяснить, что я имею в виду, вот мои цели и контекст:

public class Root 
{ 
    public int RootId { get; set; } 
    public Table1 Table1 { get; set; } 
} 

public class Table1 
{ 
    public int Table1Id { get; set; } 
    public string Name { get; set; } 
    public Table2 Table2 { get; set; } 
    public virtual ICollection<Root> Roots { get; set; } 
} 

public class Table2 
{ 
    public int Table2Id { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Table1> Table1s { get;set; } 
} 

public class Context : DbContext 
{ 
    public Context(string nameOrConnectionString) 
     : base(nameOrConnectionString) 
    { 
     Roots = Set<Root>(); 
     Table1s = Set<Table1>(); 
     Table2s = Set<Table2>(); 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    {   
     var table1 = modelBuilder.Entity<Table1>(); 
     table1.ToTable("Table1"); 
     table1.HasKey(r => r.Table1Id); 
     table1.HasRequired(r => r.Table2) 
      .WithMany(t => t.Table1s) 
      .Map(m => m.MapKey("Table2Id")); 

     var table2 = modelBuilder.Entity<Table2>(); 
     table2.ToTable("Table2"); 
     table2.HasKey(r => r.Table2Id); 

     var root = modelBuilder.Entity<Root>(); 
     root.ToTable("Root"); 
     root.HasKey(r => r.RootId); 
     root.HasRequired(r => r.Table1) 
      .WithMany(t => t.Roots) 
      .Map(m => m.MapKey("Table1Id")); 

     // TODO: Some sort of mapping    

     base.OnModelCreating(modelBuilder); 
    } 

    public DbSet<Root> Roots { get; private set; } 
    public DbSet<Table1> Table1s { get; private set; } 
    public DbSet<Table2> Table2s{ get; private set; } 
} 

В конце концов, я хотел бы запустить этот фрагмент кода (на пустой базе данных) ...

using(var c = new Context(@"connection string")) 
{ 
    c.Roots.Add(new Root 
    { 
     Table1 = new Table1 
     { 
      Name = "Test1", 
      Table2 = new Table2 { Name = "Test2" } 
     } 
    }); 
    c.SaveChanges(); 
} 

и для данных, чтобы посмотреть, как это впоследствии:

Table2 
====== 
Table2Id | Name 
     1 | Test2 

Table1 
======= 
Table1Id | Name 
     1 | Test1 

Root 
==== 
RootId | Table1Id | Table2Id 
1  |  1 |  1 

Итак, как я выполняю такое отображение? Я посмотрел на функцию «Карта» и функцию «Свойство», но я не могу понять, что я должен разместить там, где и даже если они уместны?

+0

Не могли бы вы написать больше о том, чего вы хотите достичь? В чем проблема? –

ответ

3

Благодаря @Ladislav Mrnka, указав, что он не поддерживается, и что мне понадобится свойство навигации, я решил, что у меня может быть частное свойство навигации, которое отступает к свойству Table1.Table2 и скрывает нехотя. Так что ...

Я определил личного свойства навигации в моем классе Коренного как так (обратите внимание, что это ничего не хранить, просто сдвинуто на собственность Table1.Table2):

public class Root 
{ 
    public int RootId { get; set; } 
    public Table1 Table1 { get; set; } 
    private Table2 Table2 
    { 
     get { return Table1.Table2; } 
     set { Table1.Table2 = value; } 
    } 
} 

От вопроса : Entity Framework 4 - Mapping non-public properties with CTP5 (code first) in a persistence unaware context Я создал этот маленький помощник (который просто означает, что я могу получить лямбда-выражения для частной собственности):

public interface IObjectExpressionCreator<T> 
{ 
    Expression<Func<T, TResult>> Property<TResult>(string name); 
} 

public static class PropertyExpression 
{ 
    private class ObjectExpressionCreator<T> : IObjectExpressionCreator<T> 
    { 
     public Expression<Func<T, TResult>> Property<TResult>(string name) 
     { 
      var p = Expression.Parameter(typeof(T), 
             "propertyOrFieldContainer"); 

      var body = Expression.PropertyOrField(p, name); 

      var lambda = Expression.Lambda(typeof(Func<T, TResult>), 
              body, 
              p); 

      return (Expression<Func<T, TResult>>)lambda; 
     } 
    } 
    public static IObjectExpressionCreator<T> For<T>() 
    { 
     return new ObjectExpressionCreator<T>(); 
    } 
} 

Теперь я выполнить отображение, как так:

root 
    .HasRequired(PropertyExpression.For<Root>().Property<Table2>("Table2")) 
    .WithMany() 
    .Map(m => m.MapKey("Table2Id")); 

и когда я запускаю код в вопросе, я получаю именно то, что хотел.

3

Я не хочу, свойство на моем корневой объект для Table2, вместо этого я хочу , что ID заселяться из соответствующего Table2 из Table1.

EF не поддерживает это. Вы не можете переслать значение свойства из отношения к основной таблице. Вы должны открыть навигационное свойство либо на Table2, либо на Root и сопоставить его так же, как вы сделали это для Table1.

+0

Спасибо. Что делать, если я ставил публичный int Table2Id {get; задавать; } в Root - я мог бы автоматически установить его с соответствующим свойством Table1.Table2.Table2Id? – kmp

Смежные вопросы