使用实体框架手动输入密钥 [英] Entering keys manually with Entity Framework
问题描述
我首先尝试将 Entity Framework 代码用于一个简单的数据库项目,但遇到了一个我根本无法弄清楚的问题.
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.
我注意到 EF 正在为我的表设置 ID,每次自动增加 1,完全忽略我为该字段手动输入的值.经过一番搜索,我了解到禁用此行为的正确方法是:
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:
modelBuilder.Entity<Event>().Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
但是现在我刚刚收到此错误,我不知道为什么:
However now I'm just getting this error and I have no idea why:
未处理的异常:System.Data.Entity.Infrastructure.DbUpdateException:错误更新条目时发生.请参阅内部异常细节.---
Unhandled Exception: System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---
System.Data.UpdateException:更新条目时出错.有关详细信息,请参阅内部异常.--->System.Data.SqlClient.SqlException:无法插入显式值IDENTITY_INSERT 设置为 OFF 时表 'Events' 中的标识列.
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.
如果有帮助,这里是有问题的 POCO 类:
If it's helpful, here is the POCO class in question:
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; }
}
提前致谢.
推荐答案
默认情况下,Entity Framework 假定一个整数主键是数据库生成的(相当于添加属性 HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
或在 Fluent API 中调用 Property(e => e.EventID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
.
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.
如果您查看创建表的迁移,您应该看到:
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 );
然后您使用 Fluent API 将模型更改为 DatabaseGenerated.None
.EF 将其放入迁移中:
Then you changed the model using the Fluent API to DatabaseGenerated.None
. EF puts this in the migration:
AlterColumn("dbo.Events", "EventID", c => c.Int(nullable: false, identity: false))
生成的sql是这样的:
And the sql generated is this:
ALTER TABLE [dbo].[Events] ALTER COLUMN [EventID] [int] NOT NULL
实际上确实是深蹲.从列中删除 IDENTITY 不是琐碎的.您需要删除并重新创建表或创建一个新列,然后您必须复制数据并修复外键.因此,EF 不为您做这件事也就不足为奇了.
Which actually does diddly squat. Dropping the IDENTITY from 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.
你需要想出如何最好地为自己做这件事.既然您已经指定了 DatabaseGeneratedOption.None
,您可以将迁移回滚到 0 并从头开始重新构建,或者您可以手动更改迁移以删除并重新创建表.
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.
或者您可以删除并重新创建该列:
Or you could drop and recreate the column:
DropColumn("Customer", "CustomerId");
AddColumn("Customer", "CustomerId", c => c.Long(nullable: false, identity: false));
编辑或者你可以开启身份识别/Off 使用自定义迁移操作
这篇关于使用实体框架手动输入密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!