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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 13:33:43  来源:igfitidea点击:

Entering keys manually with Entity Framework

c#sqlasp.netentity-frameworkentity-framework-core

提问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。