【问题标题】:Mapping 2 tables to single entity in Entity Framework将 2 个表映射到实体框架中的单个实体
【发布时间】:2013-02-18 14:58:03
【问题描述】:

我希望你能帮助我。

我在数据库中有 2 个表:Bill 和 BillItem。这些表在数据库中配置了一对一的关系,其中 bill 是主表,而 BillItem 是依赖表

表Bill的结构:

Int BillId (PK)
Int BillTypeId Not Null
Varchar(5) Usr Not Null
DateTime Tm Not Null

表BillItem的结构:

Int BillItemId (PK)
Int ItemId Not Null 
Varchar(5) Usr Not Null
DateTime Tm Not Null

我想使用 Fluent API 和 Entity Framework 4.1 Code First 方法将这两个表映射到单个 POCO 类

我还想将表列名称配置为在 POCO 类中使用不同的属性名称(即 Id 代替 BillId,User 代替 Usr)

这是一个旧数据库,我无法修改它的任何对象。

如何做到这一点?

谢谢大家。

生成的类应该是(如果可以的话):

public int Id {get;set;}
public int BillTypeId {get;set;}
public int ItemId {get;set;}
public string User {get;set;}
public string User1 {get;set;}
public DateTime Tm {get;set;}
public DateTime Tm1 {get;set;}

【问题讨论】:

  • 你的 POCO 类的哪些实例应该放到 Bill 表中,哪些应该放到 BillItem 表中?
  • 不能创建视图吗?
  • @lazyberezovsky 如果适用,那么班级账单应包含两个表的所有属性
  • 我无法创建视图
  • @lazyberezovsky 我已经编辑了我的问题以反映结果类。我知道我可以选择使用 Fluent API 映射到零...一对一关系,但我想将这两个表映射到一个 POCO 实体中。

标签: c# entity-framework ef-code-first code-first fluent-interface


【解决方案1】:

对于这个问题,您可以很容易地做到这一点,并且您有 2 个选项。第一种是使用实体框架(mapping multiple tables to a single entity class in entity framework)映射类。

第二种选择是手动完成: 2张表必须遵循的限制是1必须是强表,第二张必须是弱表(这样做,你应该只从强表到弱表一个接一个)否则,这不会起作用结果将是对象的集合,然后您需要确定第一个对象是否是您需要的对象,而不是其他对象。

如果您想使用稍微快一点的方法,我建议您使用您自己的逻辑来映射 POCO 对象。创建 2 个将与数据库表映射的类,并从服务对象构建对象。

这种方法很好,因为生成的 LINQ 查询不会使用 INNER JOINS,这使它更快。但连接应该远离您。

例子

int i=0;
// this 2 refer to the 2 different mapped tables in your context database
var pbdata = _pbdata.GetSingle(p=>p.StrongTableID == StrongTableID);
var pb = _pb.GetSingle(p=>p.WeakTableID == pbdata.WeakTableID);
// you can see that i am looking for the StrongTableID in order to select the entity value

// this is optional but usefull! you can do the
// "copy" inside a function where in future if the 
// object changes, you can update easily
ObjectComposite.Map(body, ref pb, ref pbdata);

// the following proccess needs to be done like this...
// first save the value in the weak object so 
// the WeakTableID is recorded
// UPDATE: maybe these 2 should go into a transact for more security... but... ok...
Save(pb);
i += this.unitOfWork.Save();
pbdata.ProfessionalBodyID = pb.ProfessionalBodyID;

// once the values for the second objects are set, save it all again.
Save(pbdata);
i += this.unitOfWork.Save();
return i > 0 ? true : false;

这种方法更快,但您需要自己控制一切。好在你可以在这里映射任意数量的表

希望对你有帮助!

【讨论】:

    【解决方案2】:

    我认为您可以使用实体拆分功能实现此目的,但您需要使用一些数据注释(无 esacpe):
    警告我没有尝试过这种方法但它可能会起作用,如果你喜欢,请检查一下 第一:使用 HasColumnName 数据注释在您的单域模型类中注释属于 BillItem 表的属性。
    第二:使用此代码示例

    public class YourSingleModelClassNameConfiguration : EntityTypeConfiguration<YourSingleModelClassName> {
        public YourSingleModelClassNameConfiguration() {
    
            ToTable("Bill"); Property(param => param.Id).IsRequired().HasColumnName("BillId");
    
            // NOW REPEAT THAT FOR ALL BILL PROPERTIES WITH YOUR REQUIRED ATTRIBUTES (ISREQUIRED OR NOT, LENGTH ...)
    
            // NOW THE PROPERTIES YOU NEED TO MAP TO THE BILL ITEMS TABLE GOES INTO THE MAP FUNCTION
            Map(
            param =>
                { param.Properties(d => new {d.ItemId, d.User1}); m.ToTable("BillItem");
                }
            );
    
            // DON'T FORGET TO MENTION THE REST OF THE PROPERTIES BELONGING TO THE BillItem TABLE INSIDE THE PROPERTIES METHOD IN THE LAST LINE.
    
        }
    }
    

    【讨论】:

      【解决方案3】:

      对于重命名列,这很简单:

      [Table("SomeHorribleTableName")]
          public class MyNiceTableName
          {
              [Column("Usr")]
              public string User { get; set; }
          }
      

      这里我也重命名了实体.. 不需要保留一个可怕的表名。关于将 2 个表映射到 1 个实体。我认为这是不可能的。看这里:Mapping data from 2 tables to 1 entity - Entity Framework 4

      流畅的风格:

      public class Bill
          {
              public int ID { get; set; }
              public int BillTypeID { get; set; }
              public string UserName { get; set; }
              public DateTime Time { get; set; }
          }
      
          public class BillItem
          {
              public int ID { get; set; }
              public int ItemID { get; set; }
              public string UserName { get; set; }
              public DateTime Time { get; set; }
          }
      
          internal class BillMap : EntityTypeConfiguration<Bill>
          {
              public BillMap()
              {
                  ToTable("Bills");
                  HasKey(x => x.ID);
                  Property(x => x.ID).HasColumnName("BillId");
                  Property(x => x.BillTypeID).IsRequired().HasColumnName("BillTypeId");
                  Property(p => p.UserName).IsRequired().HasColumnName("Usr");
                  Property(x => x.Time).IsRequired().HasColumnName("Tm");
              }
          }
      
          internal class BillItemMap : EntityTypeConfiguration<BillItem>
          {
              public BillItemMap()
              {
                  ToTable("BillItems");
                  HasKey(x => x.ID);
                  Property(x => x.ID).HasColumnName("BillItemId");
                  Property(x => x.ItemID).IsRequired().HasColumnName("ItemId");
                  Property(p => p.UserName).IsRequired().HasColumnName("Usr");
                  Property(x => x.Time).IsRequired().HasColumnName("Tm");
              }
          }
      

      这可能是我能做的最好的了。至于处理两个表中的 Usr 列,您可能应该在自己的控制器类/业务逻辑层中处理。

      还有一件事:对于上面的配置类.. 像这样在 DbContext 中调用它们:

      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
          modelBuilder.Configurations.Add(new BillMap());
          modelBuilder.Configurations.Add(new BillItemMap());
      }
      

      【讨论】:

      • 我使用的是严格的 Fluent API,没有数据注释
      • user 属性来自 Bill 表。但是 BillItem 表中的 User 属性呢?如何映射它,以及如何将该属性配置为来自 BillItem 表
      • 再看一遍。我不确定它是否可以改进更多。也许比我更有技巧的人可以改进这个……如果可能的话。
      • 这正是我现在在我的模型中所拥有的,也就是说,我在 bill 类中配置了具有单向导航属性的一对一关系。我想将这 2 个类/表映射到一个 POCO 类中。我认为没有办法做到这一点。非常感谢您的帮助。
      猜你喜欢
      • 2015-08-17
      • 1970-01-01
      • 1970-01-01
      • 2014-08-21
      • 1970-01-01
      • 1970-01-01
      • 2013-12-24
      • 2011-01-04
      • 1970-01-01
      相关资源
      最近更新 更多