使用EF5 Code First Migrations执行IDENTITY_INSERT

bry*_*ngm 7 c# asp.net-mvc entity-framework ef-migrations

我有一个POCO,我试图通过Code First Migrations创建,然后播种数据.问题是我想在播种时将特定值插入标识列.

这是我的POCO

public class Result
{
    public long ResultId { get; set; }
    public long? TeamId { get; set; }

    public Team Team { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这是我在Configuration.cs的Seed方法中的AddOrUpdate调用

context.Results.AddOrUpdate
    (
         r => r.ResultId,
         new Result { ResultId = 101, TeamId = null },
         new Result { ResultId = 201, TeamId = null }
    );
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,它不会插入101和201的值,而是插入1和2.是否有任何DataAttributes我可以应用于模型来帮助解决这个问题?

Aro*_*ron 18

这是如何通过属性/约定关闭Identity

public class Result
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public long ResultId { get; set; }
    public long? TeamId { get; set; }

    public Team Team { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这是通过EntityTypeConfiguration关闭Identity的方法

public class ResultMapper : EntityTypeConfiguration<Result>
{
    public ResultMapper()
    {
        HasKey(x => x.ResultId);
        Property(x => x.ResultId)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    }
}
Run Code Online (Sandbox Code Playgroud)

或者您可以使用OnModelCreating重载

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Result>().Property(x => x.ResultId)
               .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    }
Run Code Online (Sandbox Code Playgroud)

  • 如果OP需要IDENTIY_INSERT,那是因为它们有一个标识列.您不能只是取消该标识列来执行IDENTITY_INSERT.然后,您还需要另一次迁移才能再次为该列启用Identity.更好地使用原始SQL而不是仅针对某些插入更改数据库架构. (3认同)

Lop*_*ded 6

如果有人仍然感到困惑...

有关使IDENTITY_INSERT与Code-First Migration Seed()方法一起使用所需的其他信息,请参阅下文

我确实使用Aron的System.ComponentModel.DataAnnotations.Schema.DatabaseGenerated属性实现将模型ID的DB生成的属性设置为'None',但我仍然无法通过标识插入错误.我想我会在这里发布我的发现,以防其他人仍然遇到麻烦.

为了使它工作,我将种子方法的逻辑包装在SQL事务中,并用于context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT myTable ON")在运行.AddOrUpdate()方法之前允许插入.这是我的Configuration.vb文件(使用Google API类型的表作为示例数据):

Imports System
Imports System.Data.Entity
Imports System.Data.Entity.Migrations
Imports System.Linq

Namespace Migrations

    Friend NotInheritable Class Configuration 
        Inherits DbMigrationsConfiguration(Of DAL.MyDbContext)

        Public Sub New()
            AutomaticMigrationsEnabled = False
            AutomaticMigrationDataLossAllowed = False
        End Sub

        Protected Overrides Sub Seed(context As DAL.MyDbContext)
            '  This method will be called after migrating to the latest version.

            Dim newContext As New MyDbContext(context.Database.Connection.ConnectionString)
            Using ts = newContext.Database.BeginTransaction()

                Try

                    ' Turn on identity insert before updating
                    newContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT GoogleApiTypeGroups ON")
                    ' Make sure the expected GoogleApiTypeGroups exist with the correct names and IDs.
                    newContext.GoogleApiTypeGroups.AddOrUpdate(
                        Function(x) x.Id,
                        New GoogleApiTypeGroup() With {.Id = 1, .name = "Google Cloud APIs"},
                        New GoogleApiTypeGroup() With {.Id = 2, .name = "YouTube APIs"},
                        New GoogleApiTypeGroup() With {.Id = 3, .name = "Google Maps APIs"},
                        New GoogleApiTypeGroup() With {.Id = 4, .name = "Advertising APIs"},
                        New GoogleApiTypeGroup() With {.Id = 5, .name = "Google Apps APIs"},
                        New GoogleApiTypeGroup() With {.Id = 6, .name = "Other popular APIs"},
                        New GoogleApiTypeGroup() With {.Id = 7, .name = "Mobile APIs"},
                        New GoogleApiTypeGroup() With {.Id = 8, .name = "Social APIs"})
                    ' Attempt to save the changes.
                    newContext.SaveChanges()
                    ' Turn off the identity insert setting when done.
                    newContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT GoogleApiTypeGroups OFF")

                    ' Turn on identity insert before updating
                    newContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT GoogleApiTypes ON")
                    ' Make sure the expected GoogleApiTypes exist with the correct names, IDs, and references to their corresponding GoogleApiTypeGroup.
                    newContext.GoogleApiTypes.AddOrUpdate(
                        Function(x) x.Id,
                        New GoogleApiType() With {.Id = 1, .name = "Google Maps JavaScript API", .GoogleApiTypeGroupId = 3})
                    ' Save the changes
                    newContext.SaveChanges()
                    ' Turn off the identity insert setting when done.
                    newContext.Database.ExecuteSqlCommand("SET IDENTITY_INSERT GoogleApiTypes ON")

                    ts.Commit()
                Catch ex As Exception
                    ts.Rollback()
                    Throw
                End Try
            End Using

        End Sub

    End Class

End Namespace
Run Code Online (Sandbox Code Playgroud)