Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF Core-在EF Core 3.1或5中,什么是MapToStoredProcess替换_C#_Entity Framework Core - Fatal编程技术网

C# EF Core-在EF Core 3.1或5中,什么是MapToStoredProcess替换

C# EF Core-在EF Core 3.1或5中,什么是MapToStoredProcess替换,c#,entity-framework-core,C#,Entity Framework Core,EF Core中没有MapToStoredProcess,这很遗憾,因为它允许Add方法隐藏是否使用存储过程 我已经看过EF Core 3.1和5,但找不到推荐的替代品。所以,如果我有下面的代码,我应该如何/在哪里设置并调用一个插入存储过程或针对它选择存储过程 public class DatabaseModel : DbContext { public virtual DbSet<Office> Offices { get; set; } public Datab

EF Core中没有
MapToStoredProcess
,这很遗憾,因为它允许
Add
方法隐藏是否使用存储过程

我已经看过EF Core 3.1和5,但找不到推荐的替代品。所以,如果我有下面的代码,我应该如何/在哪里设置并调用一个插入存储过程或针对它选择存储过程

public class DatabaseModel : DbContext
{
    public virtual DbSet<Office> Offices { get; set; }

    public DatabaseModel(DbContextOptions<DatabaseModel> options) : base(options)    
    { }

    protected override void OnModelCreating(ModelBuilder modelBuilder) {}
}
公共类数据库模型:DbContext
{
公共虚拟数据库集办公室{get;set;}
公共数据库模型(DbContextOptions):基本(选项)
{ }
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder){}
}

感谢您的帮助。

EF CORE中不支持MapToStoredProcess。 您可以使用
FromSqlRaw
方法执行存储过程

var result = ctx.ParameterDetails.FromSqlRaw("EXEC dbo.get_nextparam @UserId={0}", userId).ToList();

注意:这目前没有实现SQL SERVER所做的批量插入,要使多个表使用相同的表名,您需要实现

您可以创建一个覆盖Microsoft.EntityFrameworkCore.Update.IUpdateSqlGenerator的实现,并在注册时对其执行
ReplaceService
。我已成功重写Sql Server中的插入操作

在我的例子中,直接调用存储过程不是一个选项,因为我正在尝试将一个项目从EF 6升级到EF Core,而只需进行最小的更改

正在注册DbContext:

services.AddDbContext((sp,选项)=>
{
选择权
.UseSqlServer(连接字符串)
.ReplaceService();
});
MapToProcedureUpdateSqlGenerator
使用Microsoft.EntityFrameworkCore.SqlServer.Update.Internal;
使用Microsoft.EntityFrameworkCore.Update;
使用制度;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
命名空间efcoremaptostoredprocesses
{
//小心此实现,因为它会发出警告
//这是一个支持实体框架核心基础设施的内部API
//并且不受与公共API相同的兼容性标准的约束。
公共类MaptopProcedureUpdateSqlGenerator:SqlServerUpdateSqlGenerator
{
公共MapToProcedureUpdateSqlGenerator(更新SqlGeneratorDependencies依赖项):基础(依赖项)
{
}
公共覆盖结果映射AppendInsertOperation(StringBuilder命令StringBuilder,ModificationCommand命令,int命令位置)
{
如果(command==null)抛出新的ArgumentNullException(nameof(command));
如果(commandStringBuilder==null)抛出新的ArgumentNullException(nameof(commandStringBuilder));
if(_tableInsertProcs.TryGetValue(command.TableName,out字符串procName))
{
var name=command.TableName;
var schema=command.schema;
var operations=command.ColumnModifications;
var writeOperations=operations.Where(o=>o.IsWrite.ToList();
AppendExecCommandHeader(commandStringBuilder、procName、schema、writeOperations);
if(operations.Any(=>u.IsRead))
{
返回resultsMapping.LastInResultSet;
}
返回resultsMapping.NoResultSet;
}
其他的
{
返回base.AppendInsertOperation(commandStringBuilder、command、commandPosition);
}
}
/// 
///附加用于执行存储过程的SQL片段
/// 
///SQL应附加到的生成器。
///过程的名称。
///表架构,或使用默认架构。
///表示要插入的数据的操作。
受保护的虚拟空AppendExecCommandHeader(
StringBuilder命令StringBuilder,
字符串名,
字符串模式,
IReadOnlyList操作)
{
如果(commandStringBuilder==null)抛出新的ArgumentNullException(nameof(commandStringBuilder));
if(string.IsNullOrWhiteSpace(name))抛出新的ArgumentException(“必需”,nameof(name));
如果(operations==null)抛出新的ArgumentNullException(nameof(operations));
commandStringBuilder.Append(“EXEC”);
标识符(commandStringBuilder、名称、架构);
如果(operations.Count>0)
{
commandStringBuilder
.AppendJoin(
操作,
(此项、名称、模式),
(sb,o,p)=>
{
if(o.IsWrite)
{
var(g,n,s)=p;
如果(!o.UseCurrentValueParameter)
{
抛出新的NotSupportedException(“不支持的文本”);
}
其他的
{
g、 GenerateParameterNamePlaceholder(sb,o.ColumnName);
commandStringBuilder.Append(“”);
g、 GenerateParameterNamePlaceholder(sb,o.ParameterName);
}
}
其他的
{
某人追加(“违约”);
}
});
commandStringBuilder.AppendLine(SqlGenerationHelper.StatementTerminator);
}
}
//todo使用依赖项进行配置
私人阅读

            services.AddDbContext<ExampleDbContext>((sp, options) =>
            {
                options
                    .UseSqlServer(connectionString)
                    .ReplaceService<IUpdateSqlGenerator, MapToProcedureUpdateSqlGenerator>();
            });
using Microsoft.EntityFrameworkCore.SqlServer.Update.Internal;
using Microsoft.EntityFrameworkCore.Update;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EFCoreMapToStoredProcedures
{
   // careful with this implementation as it gives warning
   // This is an internal API that supports the Entity Framework Core infrastructure
    //     and not subject to the same compatibility standards as public APIs.
    public class MapToProcedureUpdateSqlGenerator : SqlServerUpdateSqlGenerator
    {
        public MapToProcedureUpdateSqlGenerator(UpdateSqlGeneratorDependencies dependencies) : base(dependencies)
        {
        }



        public override ResultSetMapping AppendInsertOperation(StringBuilder commandStringBuilder, ModificationCommand command, int commandPosition)
        {
            if (command == null) throw new ArgumentNullException(nameof(command));
            if (commandStringBuilder == null) throw new ArgumentNullException(nameof(commandStringBuilder));

            if (_tableInsertProcs.TryGetValue(command.TableName, out string procName))
            {
                var name = command.TableName;
                var schema = command.Schema;
                var operations = command.ColumnModifications;

                var writeOperations = operations.Where(o => o.IsWrite).ToList();
                 
                AppendExecCommandHeader(commandStringBuilder, procName, schema, writeOperations);

                if (operations.Any(_ => _.IsRead))
                {
                    return ResultSetMapping.LastInResultSet;
                }

                return ResultSetMapping.NoResultSet;
            }
            else
            {
                return base.AppendInsertOperation(commandStringBuilder, command, commandPosition);
            }
        }

  
        /// <summary>
        ///     Appends a SQL fragment for excuting a stored procedure
        /// </summary>
        /// <param name="commandStringBuilder"> The builder to which the SQL should be appended. </param>
        /// <param name="name"> The name of the procedure. </param>
        /// <param name="schema"> The table schema, or <see langword="null" /> to use the default schema. </param>
        /// <param name="operations"> The operations representing the data to be inserted. </param>
        protected virtual void AppendExecCommandHeader(
            StringBuilder commandStringBuilder,
            string name,
            string schema,
            IReadOnlyList<ColumnModification> operations)
        {
            if (commandStringBuilder == null) throw new ArgumentNullException(nameof(commandStringBuilder));
            if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("required", nameof(name));
            if (operations == null) throw new ArgumentNullException(nameof(operations));
            
            commandStringBuilder.Append("EXEC ");
            SqlGenerationHelper.DelimitIdentifier(commandStringBuilder, name, schema);

            if (operations.Count > 0)
            {

                commandStringBuilder
                    .AppendJoin(
                        operations,
                        (this, name, schema),
                        (sb, o, p) =>
                        {
                            if (o.IsWrite)
                            {
                                var (g, n, s) = p;
                                if (!o.UseCurrentValueParameter)
                                {
                                    throw new NotSupportedException("literals not supported");
                                }
                                else
                                {
                                    g.SqlGenerationHelper.GenerateParameterNamePlaceholder(sb, o.ColumnName);
                                    commandStringBuilder.Append(" = ");
                                    g.SqlGenerationHelper.GenerateParameterNamePlaceholder(sb, o.ParameterName);
                                }
                            }
                            else
                            {
                                sb.Append("DEFAULT");
                            }
                        });
                commandStringBuilder.AppendLine(SqlGenerationHelper.StatementTerminator);
            }
        }


        // todo make configurable with dependencies
        private readonly Dictionary<string, string> _tableInsertProcs = new Dictionary<string, string>()
        {
            ["OrderItems"] = "InsertOrderItem"
        };
    }
}