C# 使用实体框架手动输入密钥
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18907411/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Entering keys manually with Entity Framework
提问by JCafe
I'm trying to use Entity Framework code first for a simple database project and I run into a problem I simply cannot figure out.
我试图首先将实体框架代码用于一个简单的数据库项目,但遇到了一个我根本无法弄清楚的问题。
I noticed EF was setting the ID for my tables automatically increasing by 1 each time, completely ignoring the value I entered manually for that field. After some searching it is my understanding that the right way to disable this behavior is doing:
我注意到 EF 正在为我的表设置 ID,每次自动增加 1,完全忽略我为该字段手动输入的值。经过一番搜索后,我的理解是禁用此行为的正确方法是:
modelBuilder.Entity<Event>().Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
However now I'm just getting this error and I have no idea why:
但是现在我刚刚收到此错误,我不知道为什么:
Unhandled Exception: System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---
System.Data.UpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Cannot insert explicit value for identity column in table 'Events' when IDENTITY_INSERT is set to OFF.
未处理的异常:System.Data.Entity.Infrastructure.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---
System.Data.UpdateException:更新条目时出错。有关详细信息,请参阅内部异常。---> System.Data.SqlClient.SqlException:当 IDENTITY_INSERT 设置为 OFF 时,无法为表“事件”中的标识列插入显式值。
If it's helpful, here is the POCO class in question:
如果有帮助,这里是有问题的 POCO 类:
public class Event
{
[Key, Required]
public int EventID { get; set; }
public string EventType { get; set; } //TODO: Event Type Table later on
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public virtual ICollection<Match> Matches { get; set; }
public virtual ICollection<EventParticipation> EventParticipation { get; set; }
}
Thanks in advance.
提前致谢。
采纳答案by Colin
By default Entity Framework assumes that an integer primary key is database generated (equivalent to adding the attribute HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
or calling Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
in the Fluent API.
默认情况下,Entity Framework 假定整数主键是数据库生成的(相当于添加属性HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
或Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
在 Fluent API 中调用。
If you look at the migration that creates the table you should see this:
如果您查看创建表的迁移,您应该看到:
CreateTable(
"dbo.Events",
c => new
{
EventID = c.Int(nullable: false, identity: true),
//etc
})
.PrimaryKey(t => t.EventID );
Then you changed the model using the Fluent API to DatabaseGenerated.None
. EF puts this in the migration:
然后您使用 Fluent API 将模型更改为DatabaseGenerated.None
. EF 将其放入迁移中:
AlterColumn("dbo.Events", "EventID", c => c.Int(nullable: false, identity: false))
And the sql generated is this:
生成的sql是这样的:
ALTER TABLE [dbo].[Events] ALTER COLUMN [EventID] [int] NOT NULL
ALTER TABLE [dbo].[Events] ALTER COLUMN [EventID] [int] NOT NULL
Which actually does diddly squat. Dropping the IDENTITYfrom a column is not trivial. You need to drop and recreate the table or create a new column, then you have to copy the data and fix up foreign keys. So it's not surprising that EF isn't doing that for you.
这实际上确实是深蹲。从列中删除 IDENTITY并非易事。您需要删除并重新创建表或创建一个新列,然后您必须复制数据并修复外键。因此,EF 不为您这样做也就不足为奇了。
You need to work out how best to do it for yourself. You could roll back your migrations to 0 and re-scaffold from scratch now that you have specified DatabaseGeneratedOption.None
, or you could change the migration manually to drop and recreate the table.
你需要弄清楚如何最好地为自己做这件事。您可以将迁移回滚到 0 并在您指定后从头开始重新构建脚手架DatabaseGeneratedOption.None
,或者您可以手动更改迁移以删除并重新创建表。
Or you could drop and recreate the column:
或者您可以删除并重新创建该列:
DropColumn("Customer", "CustomerId");
AddColumn("Customer", "CustomerId", c => c.Long(nullable: false, identity: false));
EDITOr you could Switch Identity On/Off With A Custom Migration Operation
编辑或者您可以使用自定义迁移操作打开/关闭身份
回答by marsze
Since I prefer attributes, here the alternative for the sake of completeness:
由于我更喜欢属性,为了完整起见,这里有一个替代方案:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
Note: This works also in EF Core.
注意:这也适用于 EF Core。