【问题标题】:EF Core - What is MapToStoredProcedures replacement in EF Core 3.1 or 5EF Core - EF Core 3.1 或 5 中的 MapToStoredProcedures 替换是什么
【发布时间】:2021-01-22 07:24:10
【问题描述】:

EF Core 中没有 MapToStoredProcedures 很遗憾,因为它允许 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) {}
}

感谢您的帮助。

【问题讨论】:

标签: c# entity-framework-core


【解决方案1】:

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

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

【讨论】:

  • ctx的对象是什么?
  • 是EF核心DbContext
【解决方案2】:

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

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

在我的情况下,直接调用存储过程不是一种选择,因为我正在尝试将项目从 EF 6 升级到 EF Core,并进行更小的更改。

注册 DbContext:


            services.AddDbContext<ExampleDbContext>((sp, options) =>
            {
                options
                    .UseSqlServer(connectionString)
                    .ReplaceService<IUpdateSqlGenerator, MapToProcedureUpdateSqlGenerator>();
            });

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"
        };
    }
}

【讨论】:

    猜你喜欢
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 2020-04-26
    • 2021-04-22
    相关资源
    最近更新 更多