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字段将是最好的。 即使在没有使用的情况下,它也比处理实体关于丢失的身份密钥的不间断错误要好得多。
- 更改表结构并添加一个主列。 更新模型
- 修改XML编辑器中的.EDMX文件,并尝试添加此特定表的标签下的新列(不起作用)
- 而不是创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时间),并通过您的克隆脚本随意添加主键列。
表只需要有一列不允许空值