entity framework:没有主键的表

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

有些表没有定义主键,因此当我创build一个新的实体数据模型时,我得到以下消息:“表/视图TABLE_NAME没有定义主键,并且不能推断出有效的主键。 / view已经被排除了,要使用这个实体,你需要检查你的模式,添加正确的密钥,并取消注释“。

如果我想使用它们并修改数据,我必须向这些表添加一个PK,还是有一个解决方法,以便我不必?

这个错误的含义正是它所说的。

即使你能解决这个问题,相信我,你不想。 可以引入的令人困惑的错误的数量是惊人的,更不用提的事实,你的performance可能会下降。

不要解决这个问题。 修复你的数据模型。

编辑:我已经看到一些人downvoting这个问题。 我想这很好,但请记住,OP询问了如何映射没有主键而不是视图表格 。 答案依然如此。 围绕EF的需求,从可pipe理性,数据完整性和性能的angular度来看,在表上使用PK是一个坏主意。

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

我认为这是由Tillito解决的:

entity framework和SQL Server视图

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

我们有同样的问题,这是解决scheme:

要强制entity framework使用列作为主键,请使用ISNULL。

要强制entity framework不要使用列作为主键,请使用NULLIF。

应用这个简单的方法是在另一个select中包装你的视图的select语句。

例:

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

回答4月26日10时在17:00 Tillito

这个解决scheme工作

即使你没有PK,也不需要手动映射。 你只需要告诉EF你的列之一是索引和索引列是不可空的。

要做到这一点,你可以使用isNull函数向你的视图添加一个行号,如下所示

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

ISNULL(id, number)是关键点,因为它告诉EF这个列可以是主键

组合键也可以使用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 }); ... } } 

EF不需要数据库上的主键。 如果是这样,你不能将实体绑定到视图。

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

埃里克

在我的情况下,我不得不将一个实体映射到一个没有主键的View。 而且,我不允许修改这个视图。 幸运的是,这个视图有一个唯一string的列。 我的解决scheme是将此列标记为主键:

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

被欺骗的EF。 工作完美,没有人注意到… 🙂

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

但是,如果有一个,但没有在DB中指定一个索引,并且不能更改DB(是的,我在Dilbert的世界中工作),则可以手动将字段映射为键。

拥有无用的身份密钥有时毫无意义。 我发现如果ID不被使用,为什么添加它? 但是,实体并不那么宽容,所以添加一个ID字段将是最好的。 即使在没有使用的情况下,它也比处理实体关于丢失的身份密钥的不间断错误要好得多。

  1. 更改表结构并添加一个主列。 更新模型
  2. 修改XML编辑器中的.EDMX文件,并尝试添加此特定表的标签下的新列(不起作用)
  3. 而不是创build一个新的主要列到退出表,我将通过涉及所有现有的列( WORKED

entity framework:添加没有主键的数据表到实体模型。

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

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

再次,这只是一个解决方法。 真正的解决scheme是修复数据模型。

从实际的angular度来看,每个表(甚至像仓库表这样的非规范化表)都应该有一个主键。 或者,如果失败了,至less应该有一个唯一的,不可空的索引。

如果没有某种独特的密钥,重复的logging可能(也将会)出现在表中,这对于ORM层而言是非常有问题的,并且也是对数据的基本理解。 有重复logging的表格可能是devise不好的一个症状。

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

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

所以引用Pratap Reddy的回应,对我们来说工作得很好。

这可能迟到回复…但是…

如果表没有主键,那么为了使EF正常工作,需要分析的场景很less。 规则是:EF将与主键的表/类一起工作。 那是跟踪…

说,你的表1.logging是唯一的:唯一性是由一个外键列:2.logging是唯一的:唯一性是由多个列的组合。 3.logging不是唯一的(大部分*)。

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

对于场景#3,您仍然可以在研究表(*是否使所有logging唯一)之后使用上述解决scheme(#1 +#2)。 如果您必须包含所有列才能使所有logging具有唯一性,那么您可能需要将主键列添加到表中。 如果此表来自第三方供应商,则将该表克隆到本地数据库(隔夜或需要多less时间),并通过您的克隆脚本随意添加主键列。

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