【问题标题】:Can I map two entities to two different tables?我可以将两个实体映射到两个不同的表吗?
【发布时间】:2016-04-15 12:54:43
【问题描述】:

我正在使用 EF 和 Code First。我尝试将两个实体映射到两个不同的表。 首先,我尝试将 Material 映射到表 Materials,然后我尝试将 PlannedMaterial 映射到 Materials 和 ScheduleRows。

一个 ScheduleRow 需要对 Materials 表中的一行有一个 Foreigtn 键。没有从 Materials 表到 ScheduleRows 表的外键。

这些是我的实体。

public class Material
{
    public int Id { get; set; }  // from material table
    public string Name { get; set; }  // from material table

    // public PlannedMaterial PlannedMaterial { get; set; } Do I need this? I don't want a relation from this side.
}

public class PlannedMaterial
{
    public int Id { get; set; }  // from *ScheduleRow table*
    public string Name { get; set; } // from *material table*
    public int SequenceNo { get; set; } // from *ScheduleRow* table

    public Material Material { get; set; } // Do I need this? I'm only interrested in the Name column from the material table
}

这些是我的桌子。

CREATE TABLE [dbo].[RunScheduleRow](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [SequenceNo] [int] NOT NULL,
    [Material_id] [int] NOT NULL)  -- FK to Material table


 CREATE TABLE [dbo].[Material](
    [Id] [int] NOT NULL,
    [Name] [nvarchar](max) NULL)

我想使用 OnModelCreating(DbModelBuilder modelBuilder) 中的 fluent API 进行此映射。是否可以?怎么样?

感谢所有想法和建议。

【问题讨论】:

  • 你显示 SQL 表的事实,有点违背代码优先的概念。¨

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


【解决方案1】:

我觉得你的设计不好。您尝试管理 ScheduleRow 和 Material Tables 之间的关系,但这种关系可以由实体框架管理。

public class Material
{
    public int Id { get; set; }  // from material table
    public string Name { get; set; }  // from material table
   public ICollection<ScheduleRow> ScheduleRows{ get; set; }

}

public class ScheduleRow
{
    public int Id { get; set; }  // from *ScheduleRow table*
      public int SequenceNo { get; set; } // from *ScheduleRow* table

    public Material  Material { get; set; } 
}

配置你的 shcema

public class YourContext: DbContext 
{
    public SchoolDBContext(): base() 
    {
    }

    public DbSet<Material> Materials { get; set; }
    public DbSet<ScheduleRow> ScheduleRows { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Configure default schema
        modelBuilder.HasDefaultSchema("YourShema");
    }
}

将实体映射到表

命名空间 CodeFirst_FluentAPI_Tutorials {

 public class YourContext: DbContext 
    {
        public YourDBContext(): base() 
        {
        }

        public DbSet<Material> Materials { get; set; }
        public DbSet<ScheduleRow> ScheduleRows { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
                //Configure default schema
            modelBuilder.HasDefaultSchema("YourSchema");

            //Map entity to table
            modelBuilder.Entity<Material>().ToTable("Material");
            modelBuilder.Entity<ScheduleRow>().ToTable("RunScheduleRow","dbo");

        }
    }
}

要配置列名,请将此指令添加到上下文中

 modelBuilder.Entity<YourEntity>()
                    .Property(p => p.propertyname)
                    .HasColumnName("Caolum_name")
                    .HasColumnOrder(your_column_order)
                    .HasColumnType("column_type");

希望对你有所帮助。

【讨论】:

    【解决方案2】:

    在您跳到解决方案之前,请阅读本文,它将阐明 EF 实体的用户用途和用途,因为我可以向您保证,这不是您想的那样。

    EF 规则:

    1. 像您的类这样的 EF 实体必须可转换为 SQL 表。
    2. 其他对象的数据链接也是如此。例如,如果您制作自己的类型,则本机不支持。
    3. 查询也是如此。在 EF 中,使用的列表类型主要是 IEnumerable(只读)和 ICollection(读/写)。如果您永远不会再次发布回数据库,那么使用数组和列表等是可以接受的。¨

    那么你错过了什么? 我的好先生,您缺少第 1 条规则。所以您必须创建一个软实体(常规 DTO/模型/类)

    有点像这样。但请注意,现在 PlannedMaterial 没有保存在任何地方。

    public class PlannedMaterial
    {
        public PlannedMaterial(ScheduleRow s, Material m){
            ScheduleRow = s;
            Material = m;
        }
        public int Id { get{return _s.Id; } set{_s.Id = value;} }
        public string Name { get{return _m.Name; } set{_m.Name = value; }
        public int SequenceNo { get{return _s.SequenceNo; } set{_s.SequenceNo = value; } 
    
        Material _m{ get; set; }
        ScheduleRow _s{ get; set; }
    }
    

    这里是如何做你的实体

    public class Material
    {
        public int Id { get; set; }
        public string Name { get; set; }
    
        public virtual ICollection<ScheduleRow> ScheduleRows { get; set; } 
    }
    
    public class ScheduleRow 
    {
        public int Id { get; set; }
        public int SequenceNo { get; set; }
    
        public virtual Material Material { get; set; } 
    }
    

    上下文(参见构建器)

    public class YourContext: DbContext 
    {
        public SchoolDBContext(): base() 
        {
        }
    
        public DbSet<Material> Materials { get; set; }
        public DbSet<ScheduleRow> ScheduleRows { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //Fluent API
            modelBuilder.Entity<Material>()
                .HasMany(e => e.ScheduleRow)
                .WithRequired(e => e.Material)
                .HasForeignKey(e => e.Id)
                .WillCascadeOnDelete(false);
    
            base.OnModelCreating(modelBuilder);
        }
    }
    

    链接: FluentAPI

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多