【问题标题】:What convention maps poco properties to columns automatically? And how can I disable that auto-mapping?什么约定自动将 poco 属性映射到列?以及如何禁用该自动映射?
【发布时间】:2014-10-09 23:47:44
【问题描述】:

我有现有的 poco 模型和一个我想与 EF 6 一起使用的现有数据库。但是我的许多模型具有不映射到数据库中的列的属性。当 EF 向 sql 发送一条 select 语句时,它会要求提供这些属性,就像它们是列一样,但由于列不存在,EF 最终会抛出“无效的列名”异常。

在 EF 6 中是否有约定让所有 poco 属性都被视为列类型?如果是这样,哪个公约对此负责?如果不是,还有什么其他机制导致了这种行为,我该如何禁用它?

理想情况下,如果我将 poco 属性显式映射到 EntityTypeConfiguration 中,我希望我的实现仅将其视为数据库中的一列:

public class MyPocoMap : EntityTypeConfiguration<Authorization>
{
    public MyPocoMap()
    {
        this.Property(t => t.MyPropName).HasColumnName("MyColumnName");
    }
}

并且不必为我希望 EF 映射的所有属性执行此操作:

this.Ignore(t => t.MyPropName);

这是我如何进行映射的示例。我想找到一种方法来禁用 NotColumn1 和 NotColumn2 属性的映射,而无需显式使用 fluent api 来忽略这些属性中的每一个。

public class MyContext : DbContext
{
    static MyContext()
    {
        Database.SetInitializer<MyContext>(null);
    }

    public MyContext()
        : base("Name=MyContext")
    {
    }

    public DbSet<MyModel> MyModels { get; set; }

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

public class MyModel
{
    public int CustomId { get; set; }
    public string MyColumn1 { get; set; }
    public string MyColumn2 { get; set; }
    public string NotColumn1 { get; set; }
    public string NotColumn2 { get; set; }
}

public class MyModelMap : EntityTypeConfiguration<MyModel>
{
    public MyModelMap()
    {
        this.ToTable("MyTable");
        this.HasKey(t => t.CustomId);
        this.Property(t => t.MyColumn1).HasColumnName("Column1Name");
        this.Property(t => t.MyColumn2).HasColumnName("Column2Name");
        this.Ignore(t => t.NotColumn1);
        this.Ignore(t => t.NotColumn2);
    }
}

【问题讨论】:

  • 您使用代码、模型还是数据库优先?
  • @abatishchev 我首先使用代码,主要是手动映射所有内容...尽管我使用外部的 EF Powertools Beta 4“逆向工程代码优先”工具生成了很多映射代码我的解决方案,然后手动为每个 poco/poco-mapping 引入我需要的东西。
  • @rafe 你解决了吗?
  • 想知道您是否对此有任何更新。我知道当您对数据库进行多版本控制并希望精确控制何时映射某些属性时,这是一个巨大的麻烦(因为某些数据库版本可能没有它们或有不同的列)。但是,我还没有找到要删除的特定约定...

标签: c# .net entity-framework ef-code-first entity-framework-6


【解决方案1】:

EF6 中,您可以使用以下自定义约定代码:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Properties() 
                .Where(p => p.Name == "SomePropertyName") 
                .Configure(p => p.Ignore()); 
} 

你可以在这个address找到更多EF6的自定义代码对话

【讨论】:

  • 所以只需删除 '.Where(p => p.Name == "SomePropertyName")' 即可获得此问题的具体答案!这似乎是一种不寻常的工作方式,但您不觉得吗?
  • @Colin,如果不是删除 Where 子句,而是将其替换为 .Where(p=>string.IsNullOrEmpty(p.ColumnName)) 之类的内容,这就是答案。但是,如果我可以找到列名(通过 .HasColumnName())已设置(通过 .HasColumnName()),则无法访问内部状态。我尝试使用反射来获取内部 ColumnName 属性,但对于我来说,我无法弄清楚如何获得它......它是在通过委托传递的对象上定义的。但无论如何,如果没有这样的 where 子句,每个实体上的每个属性都将被忽略。
  • @Rafe 我以为您希望默认情况下忽略每个实体上的每个属性?如果你把这一行放在前面,设置默认值,然后写this.Property(t =&gt; t.MyPropName).HasColumnName("MyColumnName");,会发生什么?代码约定在最后获胜的基础上起作用
  • @Colin 我会尝试,但我认为 .HasColumnName() 和 .Ignore() 在内部独立工作。我认为“最后获胜”仅适用于使用相同操作的配置映射,例如,如果有两次调用 .HasColumnName(),则第二次将“获胜”。
  • @Rafe 也许你应该请求.NoticeMeAgain() 方法... ;-)
【解决方案2】:

来自System.ComponentModel.DataAnnotations.Schema;Code First Data Annotation [NotMapped] 就足够了。

public class MyModel
{
    public int CustomId { get; set; }
    public string MyColumn1 { get; set; }
    public string MyColumn2 { get; set; }
    [Not Mapped]
    public string NotColumn1 { get; set; }
    [Not Mapped]
    public string NotColumn2 { get; set; }
}

【讨论】:

  • 啊,是的,这也是另一个阻止自动映射的选项。我正在寻找一种禁用自动映射约定的方法,这样您就不必通过使用注释或使用流利的 api 的 .Ignore() 来“取消映射”这样的每一列。但是感谢您发布此信息 - 很高兴能够作为完整性的答案!
猜你喜欢
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多