C# 在.net core 2中为多个表插入标识\u

C# 在.net core 2中为多个表插入标识\u,c#,sql-server,entity-framework,asp.net-core-2.0,C#,Sql Server,Entity Framework,Asp.net Core 2.0,我正在尝试将数据从现有数据库迁移到新数据库。旧数据库非常复杂,这意味着大多数表都与许多其他基于外来ID的表有关系。我遇到了一个插入ID的解决方案: using (var context = new EmployeeContext()) { context.Employees.Add(new Employee { EmployeeId = 100, Name = "John Doe" }); context.Employees.Add(new Employee { Employee

我正在尝试将数据从现有数据库迁移到新数据库。旧数据库非常复杂,这意味着大多数表都与许多其他基于外来ID的表有关系。我遇到了一个插入ID的解决方案:

using (var context = new EmployeeContext())
{
    context.Employees.Add(new Employee { EmployeeId = 100, Name = "John Doe" });
    context.Employees.Add(new Employee { EmployeeId = 101, Name = "Jane Doe" });

    context.Database.OpenConnection();
    try
    {
        context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Employees ON");
        context.SaveChanges();
        context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Employees OFF");
    }
    finally
    {
        context.Database.CloseConnection();
    }


    foreach (var employee in context.Employees)
    {
        Console.WriteLine(employee.EmployeeId + ": " + employee.Name);
    }
}
从本Microsoft指南:


在应用
context.SaveChanges()之前,是否有方法在多个表上设置
IDENTITY\u INSERT

不。查看IDENTITY_INSERT的文档

它明确指出:

在任何时候,会话中只有一个表可以具有标识\u INSERT 属性设置为ON。如果表已将此属性设置为“开”, 并为另一个表发出SET IDENTITY_INSERT ON语句, SQL Server返回一条错误消息,指出SET IDENTITY\u INSERT为 已启用,并报告为其设置的表


没有。查看IDENTITY_INSERT的文档

它明确指出:

在任何时候,会话中只有一个表可以具有标识\u INSERT 属性设置为ON。如果表已将此属性设置为“开”, 并为另一个表发出SET IDENTITY_INSERT ON语句, SQL Server返回一条错误消息,指出SET IDENTITY\u INSERT为 已启用,并报告为其设置的表


我在这里遇到了同样的问题,当时我从存储在json文件中的对象树中播种数据

例如:

jsonData = System.IO.File.ReadAllText(@"Data\InputParameters.json");
var inputParameters = JsonConvert.DeserializeObject<List<ParameterCategory>> jsonData, settings);
context.AddRange(inputParameters);
context.SaveChanges();
jsonData=System.IO.File.ReadAllText(@“Data\InputParameters.json”);
var inputParameters=JsonConvert.DeserializeObject jsonData,设置);
AddRange(inputParameters);
SaveChanges();
在查看了EFCore源代码后,我提出了以下解决方案:

1。创建一个新类“SQLServerUpdateSqlGeneratorInCertidentity”,该类负责为每个插入操作打开和关闭标识插入:

using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.EntityFrameworkCore.SqlServer.Update.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Update;

/// <summary>
/// SqlServerUpdateSqlGenerator with Insert_Identity.
/// </summary>
public class SqlServerUpdateSqlGeneratorInsertIdentity : SqlServerUpdateSqlGenerator
{
    /// <summary>
    /// Initializes a new instance of the <see cref="SqlServerUpdateSqlGeneratorInsertIdentity"/> class.
    /// </summary>
    /// <param name="dependencies">The dependencies.</param>
    public SqlServerUpdateSqlGeneratorInsertIdentity(UpdateSqlGeneratorDependencies dependencies)
        : base(dependencies)
    {
    }

    /// <inheritdoc/>
    public override ResultSetMapping AppendBulkInsertOperation(
        StringBuilder commandStringBuilder,
        IReadOnlyList<ModificationCommand> modificationCommands,
        int commandPosition)
    {
        var columns = modificationCommands[0].ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName)
            .ToList();
        var schema = modificationCommands[0].Schema;
        var table = modificationCommands[0].TableName;

        GenerateIdentityInsert(commandStringBuilder, table, schema, columns, on: true);
        var result = base.AppendBulkInsertOperation(commandStringBuilder, modificationCommands, commandPosition);
        GenerateIdentityInsert(commandStringBuilder, table, schema, columns, on: false);

        return result;
    }

    private void GenerateIdentityInsert(
        StringBuilder builder,
        string table,
        string schema,
        IEnumerable<string> columns,
        bool on)
    {
        var stringTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(string));

        builder.Append("IF EXISTS (SELECT * FROM [sys].[identity_columns] WHERE").Append(" [name] IN (")
            .Append(string.Join(", ", columns.Select(stringTypeMapping.GenerateSqlLiteral)))
            .Append(") AND [object_id] = OBJECT_ID(").Append(
                stringTypeMapping.GenerateSqlLiteral(
                    Dependencies.SqlGenerationHelper.DelimitIdentifier(table, schema))).AppendLine("))");

        builder.Append("SET IDENTITY_INSERT ")
            .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(table, schema)).Append(on ? " ON" : " OFF")
            .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
    }
}
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用Microsoft.EntityFrameworkCore.SqlServer.Update.Internal;
使用Microsoft.EntityFrameworkCore.Storage;
使用Microsoft.EntityFrameworkCore.Update;
/// 
///SqlServerUpdateSqlGenerator具有Insert_标识。
/// 
公共类SQLServerUpdateSqlGeneratorInEntity:SqlServerUpdateSqlGenerator
{
/// 
///初始化类的新实例。
/// 
///依赖关系。
公共SqlServerUpdateSqlGeneratorInsertIdentity(UpdateSqlGeneratorDependencies依赖项)
:base(依赖项)
{
}
/// 
公共覆盖结果映射AppendBulkInsertOperation(
StringBuilder命令StringBuilder,
IReadOnlyList修改命令,
int命令位置)
{
var columns=modificationCommands[0]。ColumnModifications.Where(o=>o.IsWrite)。选择(o=>o.ColumnName)
.ToList();
var schema=modificationCommands[0]。架构;
var table=modificationCommands[0]。TableName;
GenerateIdentityInsert(commandStringBuilder、表、架构、列、on:true);
var result=base.AppendBulkInsertOperation(commandStringBuilder、modificationCommands、commandPosition);
GenerateIdentityInsert(commandStringBuilder、表、架构、列、on:false);
返回结果;
}
私有void GenerateIdentityInsert(
StringBuilder,
字符串表,
字符串模式,
IEnumerable列,
(开玩笑)
{
var stringTypeMapping=Dependencies.TypeMappingSource.GetMapping(typeof(string));
builder.Append(“如果存在(从[sys].[identity\u columns]WHERE]中选择*)。Append(“[name]”在(“)
.Append(string.Join(“,”,columns.Select(stringTypeMapping.GenerateSqlLiteral)))
.Append(“)和[object\u id]=object\u id(“).Append(
stringTypeMapping.GenerateSqlLiteral(
Dependencies.SqlGenerationHelper.differentifier(表、模式)).AppendLine(“)”;
builder.Append(“设置标识\u插入”)
.Append(Dependencies.SqlGenerationHelper.differentifier(表、架构)).Append(开?:“关”)
.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
}
}
2.用继承的新“SqlServerUpdateSqlGenerator”替换原来的“SqlServerUpdateSqlGenerator”:

在Startup.cs-ConfigureServices中,使用以下代码:

services.AddDbContext<YourDataContext>(options =>
{
    options.UseSqlServer(YourConnectionString);
    options.ReplaceService<ISqlServerUpdateSqlGenerator, SqlServerUpdateSqlGeneratorInsertIdentity>();
});
services.AddDbContext(选项=>
{
选项。使用SQLServer(您的连接字符串);
options.ReplaceService();
});
在YourDataContext.cs中-on配置使用此选项(未测试):

options.ReplaceService();
播种后,可能需要将服务配置重置为原始配置。就我而言,它不是


希望这能帮助某人…

我在这里遇到了同样的问题,当时我正在从存储在json文件中的对象树中播种数据

例如:

jsonData = System.IO.File.ReadAllText(@"Data\InputParameters.json");
var inputParameters = JsonConvert.DeserializeObject<List<ParameterCategory>> jsonData, settings);
context.AddRange(inputParameters);
context.SaveChanges();
jsonData=System.IO.File.ReadAllText(@“Data\InputParameters.json”);
var inputParameters=JsonConvert.DeserializeObject jsonData,设置);
AddRange(inputParameters);
SaveChanges();
在查看了EFCore源代码后,我提出了以下解决方案:

1。创建一个新类“SQLServerUpdateSqlGeneratorInCertidentity”,该类负责为每个插入操作打开和关闭标识插入:

using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.EntityFrameworkCore.SqlServer.Update.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Update;

/// <summary>
/// SqlServerUpdateSqlGenerator with Insert_Identity.
/// </summary>
public class SqlServerUpdateSqlGeneratorInsertIdentity : SqlServerUpdateSqlGenerator
{
    /// <summary>
    /// Initializes a new instance of the <see cref="SqlServerUpdateSqlGeneratorInsertIdentity"/> class.
    /// </summary>
    /// <param name="dependencies">The dependencies.</param>
    public SqlServerUpdateSqlGeneratorInsertIdentity(UpdateSqlGeneratorDependencies dependencies)
        : base(dependencies)
    {
    }

    /// <inheritdoc/>
    public override ResultSetMapping AppendBulkInsertOperation(
        StringBuilder commandStringBuilder,
        IReadOnlyList<ModificationCommand> modificationCommands,
        int commandPosition)
    {
        var columns = modificationCommands[0].ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName)
            .ToList();
        var schema = modificationCommands[0].Schema;
        var table = modificationCommands[0].TableName;

        GenerateIdentityInsert(commandStringBuilder, table, schema, columns, on: true);
        var result = base.AppendBulkInsertOperation(commandStringBuilder, modificationCommands, commandPosition);
        GenerateIdentityInsert(commandStringBuilder, table, schema, columns, on: false);

        return result;
    }

    private void GenerateIdentityInsert(
        StringBuilder builder,
        string table,
        string schema,
        IEnumerable<string> columns,
        bool on)
    {
        var stringTypeMapping = Dependencies.TypeMappingSource.GetMapping(typeof(string));

        builder.Append("IF EXISTS (SELECT * FROM [sys].[identity_columns] WHERE").Append(" [name] IN (")
            .Append(string.Join(", ", columns.Select(stringTypeMapping.GenerateSqlLiteral)))
            .Append(") AND [object_id] = OBJECT_ID(").Append(
                stringTypeMapping.GenerateSqlLiteral(
                    Dependencies.SqlGenerationHelper.DelimitIdentifier(table, schema))).AppendLine("))");

        builder.Append("SET IDENTITY_INSERT ")
            .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(table, schema)).Append(on ? " ON" : " OFF")
            .AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
    }
}
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用Microsoft.EntityFrameworkCore.SqlServer.Update.Internal;
使用Microsoft.EntityFrameworkCore.Storage;
使用Microsoft.EntityFrameworkCore.Update;
/// 
///SqlServerUpdateSqlGenerator具有Insert_标识。
/// 
公共类SQLServerUpdateSqlGeneratorInEntity:SqlServerUpdateSqlGenerator
{
/// 
///初始化类的新实例。
/// 
///依赖关系。
公共SqlServerUpdateSqlGeneratorInsertIdentity(UpdateSqlGeneratorDependencies依赖项)
:base(依赖项)
{
}