首页 文章

实体框架:没有主键的表

提问于
浏览
146

我有一个现有的数据库,我想用EF4.0构建一个新的应用程序

某些表没有定义主键,因此当我创建新的实体数据模型时,我收到以下消息:“表/视图TABLE_NAME没有定义主键,也没有推断出有效的主键 . 此表/视图已被排除 . 要使用该实体,您需要检查您的架构,添加正确的密钥,并取消注释“ .

如果我想使用它们并修改数据,我是否必须在这些表中添加PK,或者是否有解决方法以便我不必?

15 回答

  • 100

    The error means exactly what it says.

    即使你可以解决这个问题,相信我,你也不愿意 . 可能引入的混乱错误的数量是惊人的,可怕的,更不用说你的表现可能会下降的事实 .

    不要解决这个问题 . 修复您的数据模型 .

    EDIT: 我很好,我想,但请记住,OP询问了如何在没有主键的情况下映射 table ,而不是 view . 答案仍然是一样的 . 从可管理性,数据完整性和性能的角度来看,解决EF需要在表上使用PK是一个坏主意 .

    有些人评论说,他们没有能力修复底层数据模型,因为他们正在映射到第三方应用程序 . 这不是一个好主意,因为模型可以从你身下改变 . 可以说,在这种情况下,你想要映射到一个视图,这也不是OP所要求的 .

  • 5

    我认为这是由蒂利托解决的:

    Entity Framework and SQL Server View

    我将在下面引用他的条目:

    我们遇到了同样的问题,这就是解决方案:

    要强制实体框架使用列作为主键,请使用ISNULL .

    要强制实体框架不使用列作为主键,请使用NULLIF .

    一种简单的方法是将视图的select语句包装在另一个select中 .

    例:

    SELECT
      ISNULL(MyPrimaryID,-999) MyPrimaryID,
      NULLIF(AnotherProperty,'') AnotherProperty
      FROM ( ... ) AS temp
    

    2010年4月26日17:00由Tillito回答

  • 0

    复合键也可以使用Entity Framework Fluent API完成

    public class MyModelConfiguration : EntityTypeConfiguration<MyModel>
    {
         public MyModelConfiguration()
         {
            ToTable("MY_MODEL_TABLE");
            HasKey(x => new { x.SourceId, x.StartDate, x.EndDate, x.GmsDate });
            ...
         }
    }
    
  • -6

    在我的情况下,我必须将实体映射到View,它没有主键 . 而且,我不允许修改此视图 . 幸运的是,这个View有一个列是唯一的字符串 . 我的解决方案是将此列标记为主键:

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    [StringLength(255)]
    public string UserSID { get; set; }
    

    被骗的EF . 工作得很好,没有人注意到...... :)

  • 1

    这个解决方案有效

    即使您没有PK,也不需要手动映射 . 您只需告诉EF您的某个列是索引,索引列不可为空 .

    为此,您可以使用isNull函数向视图添加行号,如下所示

    select 
        ISNULL(ROW_NUMBER() OVER (ORDER BY xxx), - 9999) AS id
    from a
    

    ISNULL(id, number) 是此处的关键点,因为它告诉EF该列可以是主键

  • 2

    EF不需要数据库上的主键 . 如果是,则无法将实体绑定到视图 .

    您可以修改SSDL(和CSDL)以将唯一字段指定为主键 . 如果你没有一个独特的领域,那么我相信你已经被软化了 . 但你真的应该有一个独特的领域(和PK),否则你将在以后遇到问题 .

    埃里克

  • 2

    如果我想使用它们并修改数据,我是否必须在这些表中添加PK,或者是否有解决方法以便我不必?

    对于那些达到这个问题并且正在使用Entity Framework Core的人,您不再需要为表格添加PK或执行任何变通方法 . 自EF Core 2.1以来我们有一个新功能Query Types

    查询类型必须用于:

    作为ad hoc FromSql()查询的返回类型 . 映射到数据库视图 . 映射到未定义主键的表 . 映射到模型中定义的查询 .

    所以在你的DbContext中只需添加类型 DbQuery<T> 的以下属性而不是 DbSet<T> ,如下所示 . 假设您的表名是 MyTable

    public DbQuery<MyTable> MyTables { get; set; }
    
  • 4

    如果你真的没有PK,上面的答案是正确的 .

    但是如果有一个,但它没有在数据库中指定索引,并且您无法更改数据库(是的,我在Dilbert的世界中工作),您可以手动将字段映射为关键字 .

  • 12

    拥有无用的身份密钥有时是毫无意义的 . 我发现如果不使用ID,为什么要添加它?但是,实体并不那么宽容,因此添加ID字段会是最好的 . 即使在没有使用它的情况下,它也比处理Entity关于丢失的身份密钥的不断错误更好 .

  • 2

    这只是@Erick T答案的补充 . 如果没有具有唯一值的单个列,则解决方法是使用复合键,如下所示:

    [Key]
    [Column("LAST_NAME", Order = 1)]
    public string LastName { get; set; }
    
    [Key]
    [Column("FIRST_NAME", Order = 2)]
    public string FirstName { get; set; }
    

    同样,这只是一种解决方法 . 真正的解决方案是修复数据模型 .

  • 55
    • 更改表结构并添加主列 . 更新模型

    • 在XML编辑器中修改.EDMX文件并尝试在此特定表的标记下添加新列(不会工作)

    • 我将创建一个复合键,而不是创建一个新的主列到退出表涉及所有现有列( WORKED

    Entity Framework: Adding DataTable with no Primary Key to Entity Model.

  • 1

    这可能是迟到的回复...但是......

    如果表没有主键,则需要分析的场景很少,以使EF正常工作 . 规则是:EF将使用具有主键的表/类 . 这就是它跟踪的方式......

    比如,您的表1.记录是唯一的:唯一性由单个外键列产生:2 . 记录是唯一的:唯一性由多个列的组合构成 . 3.记录不是唯一的(大多数情况下*) .

    对于场景#1和#2,您可以将以下行添加到DbContext模块OnModelCreating方法:modelBuilder.Entity() . HasKey(x => new {x.column_a,x.column_b}); //尽可能多的列使记录唯一 .

    对于场景#3,您在研究表格后仍然可以使用上述解决方案(#1#2)(*无论如何都会使所有记录都是唯一的) . 如果必须包含所有列以使所有记录唯一,那么您可能需要向表中添加主键列 . 如果此表来自第三方供应商,而不是将此表克隆到本地数据库(一夜之间或需要的时间),并通过克隆脚本任意添加主键列 .

  • 4

    从实际的角度来看,每个表 - 甚至像仓库表一样的非规范化表 - 都应该有一个主键 . 或者,如果不这样做,它至少应该具有唯一的,不可为空的索引 .

    如果没有某种独特的密钥,重复的记录可以(并且将会)出现在表中,这对于ORM层和基本的数据理解都是非常有问题的 . 具有重复记录的表可能是设计错误的症状 .

    至少,该表至少应该有一个标识列 . 在SQL Server中添加自动生成ID列大约需要2分钟,在Oracle中需要5分钟 . 为了付出额外的努力,将避免许多许多问题 .

  • 0

    我们也遇到了这个问题,虽然我们有一个有空值的列,但重要的是我们有一个没有空值的依赖列,并且这两列的组合是唯一的 .

    因此,引用Pratap Reddy给出的回应,它对我们来说很好 .

  • 5

    该表只需要有一个不允许空值的列

相关问题