如何强制实体框架插入标识列?

16 浏览
0 Comments

如何强制实体框架插入标识列?

我想用一些C#代码来初始化我的数据库,并插入一些种子数据。显然,这将需要能够在插入时设置各种标识列的值。我采用了代码优先的方法。默认情况下,DbContext处理数据库连接,所以无法使用SET IDENTITY_INSERT [dbo].[MyTable] ON。因此,我目前所做的是使用允许我指定要使用的数据库连接的DbContext构造函数。然后,在该数据库连接中设置IDENTITY_INSERTON,然后尝试使用Entity Framework插入我的记录。下面是我目前的示例:

public class MyUserSeeder : IEntitySeeder {
    public void InitializeEntities(AssessmentSystemContext context, SqlConnection connection) {
        context.MyUsers.Add(new MyUser { MyUserId = 106, ConceptPersonId = 520476, Salutation = "Mrs", Firstname = "Novelette", Surname = "Aldred", Email = null, LoginId = "520476", Password="28c923d21b68fdf129b46de949b9f7e0d03f6ced8e9404066f4f3a75e115147489c9f68195c2128e320ca9018cd711df", IsEnabled = true, SpecialRequirements = null });
        try {
            connection.Open();
            SqlCommand cmd = new SqlCommand("SET IDENTITY_INSERT [dbo].[MyUser] ON", connection);
            int retVal = cmd.ExecuteNonQuery();
            context.SaveChanges();
        }
        finally {
            connection.Close();
        }
    }
}

如此接近,却又如此遥远 - 因为,虽然cmd.ExecuteNonQuery()工作正常,但当我运行context.SaveChanges()时,我收到了一个通知:“在将IDENTITY_INSERT设置为ON时,或者在复制用户插入到一个NOT FOR REPLICATION标识列时,必须为'MyUser'表中的标识列指定显式值。”

也许是因为MyUserId(即MyUser表中的标识列)是主键,所以当我调用context.SaveChanges()时,Entity Framework不会尝试设置它,即使我为MyUser实体的MyUserId属性提供了一个值。

有没有办法强制Entity Framework尝试插入实体的主键值?或者有没有办法暂时将MyUserId标记为不是主键值,这样EF就会尝试插入它?

0
0 Comments

如何强制实体框架插入自增列?

有人在EF5与DB first中遇到了这个问题:我无法让任何解决方案起作用,但我找到了另一个解决办法:

在运行.SaveChanges()命令之前,我重置表的自增计数器:

Entities.Database.ExecuteSqlCommand(String.Format(“DBCC CHECKIDENT([TableNameHere],RESEED,{0})”,newObject.Id-1));
Entities.YourTable.Add(newObject);
Entities.SaveChanges();

这意味着每次添加后都需要应用.SaveChanges() - 但至少它可以工作!

嘿,你的解决方案适用于更新目的,但我这边现在出现了一个问题,它只从主键0开始添加第一条记录。

救命稻草,修改列的解决方案并不理想,因为你需要两次更新生产服务器。这个方法非常完美。只需记住,当你知道你将插入第一条记录时,移除-1

为什么第一行插入时ID不正确?

如果插入代码可能同时运行(例如典型的网站的一部分),请确保将SQL命令和行添加包装在事务中。否则,偶尔,你的应用程序会认为新对象具有一个ID,而SQL Server却存储了另一个ID。调试起来非常有趣!

在使用EF时,如何将上述三个命令包装在事务中?

使用EF内置的事务支持(EF)或者EF Core

0
0 Comments

如何强制实体框架插入标识列?

有时候,在使用Entity Framework进行插入操作时,我们希望手动指定标识列的值。然而,默认情况下,Entity Framework会自动为标识列生成值,而不接受手动指定。

解决这个问题的方法是使用事务和执行原始SQL语句。下面是一种解决方案:

1. 首先,我们需要创建一个数据上下文实例,并开始一个事务:

using (var dataContext = new DataModelContainer())
using (var transaction = dataContext.Database.BeginTransaction())
{
    // 在事务中进行操作
}

2. 然后,我们创建一个新的实体对象,并手动指定标识列的值:

var user = new User()
{
    ID = id,
    Name = "John"
};

3. 接下来,我们使用ExecuteSqlCommand方法执行原始SQL语句,将IDENTITY_INSERT设置为ON,以允许手动插入标识列的值:

dataContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[User] ON");

4. 然后,我们将实体对象添加到数据上下文中,并调用SaveChanges方法保存更改:

dataContext.User.Add(user);
dataContext.SaveChanges();

5. 最后,我们再次使用ExecuteSqlCommand方法将IDENTITY_INSERT设置为OFF,以关闭手动插入标识列的功能:

dataContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[User] OFF");

6. 最后,我们提交事务,完成操作:

transaction.Commit();

需要注意的是,如果我们在模型设计中将标识列的StoreGeneratedPattern属性设置为None,则可以避免出现错误。但这样做会导致无法使用正常方式(即不手动指定标识列的值)插入对象。

总结起来,以上方法可以解决Entity Framework不插入标识列的问题。需要注意的是,这种方法只是强制插入标识列的值,而不是解决Entity Framework不插入标识列的问题。同时,我们还需要注意事务的使用和SQL语句的执行方法的选择。

0
0 Comments

如何强制实体框架插入标识列?

问题原因:实体框架默认情况下不会自动插入标识列,需要手动设置。

解决方法:

1. 使用ObjectContext.ExecuteStoreCommand方法来执行SQL命令,可以绕过实体框架的中间层。

2. 在执行插入操作之前,使用context.ExecuteStoreCommand("SET IDENTITY_INSERT [dbo].[MyUser] ON");命令告诉数据库开启标识列插入。

3. 如果使用Code First方法,需要在OnModelCreating方法中使用Property(obj => obj.MyUserId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None).HasColumnName("MyUserId");命令告诉实体框架该列不是由数据库生成的。

4. 如果需要在OnModelCreating方法执行之后告诉实体框架该信息,则需要创建一个专门用于执行标识列插入的实体,并在OnModelCreating方法中进行配置。

5. 如果使用“数据库优先”模式,则可以在设计器中右键点击列,打开属性窗口,将[StoreGeneratedPattern]设置为[none]

以上是解决问题的方法,希望能对你有所帮助!

0