c# - 如何使用 EntityFramework 7 和 Asp.Net 5 调用 SQL 存储过程

标签 c# sql-server asp.net-core-mvc entity-framework-core ef-database-first

最近几天我正在搜索一些关于如何调用 Stored Procedure 的教程。从内部 Web API使用 EntityFramework 7 的 Controller 方法.

我完成的所有教程都以相反的方式显示它,即 Code First方法。但是我已经有了一个数据库,我需要用它来构建一个 Web API .各种业务逻辑已经编写为存储过程和 View ,我必须从我的 Web API 中使用它们。

问题 1:这是否可以继续 Database First使用 EF7 的方法并像上面那样使用数据库对象?

我安装了 EntityFramework 6.1.3通过以下 NuGet 到我的包裹命令:

install-package EntityFramework 它将 6.1.3 版本添加到我的项目中,但立即开始向我显示错误消息(请参见下面的屏幕截图)。我不知道如何解决这个问题。

enter image description here

我有另一个测试项目,在 project.json 中我可以看到如下两个条目:

"EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final", "EntityFramework.MicrosoftSqlServer.Design": "7.0.0-rc1-final",

但是,当我在 Nu-Get 中搜索时包管理器,我看不到这个版本!只有 6.1.3 即将推出。

我的主要目标是使用现有数据库中已编写的存储过程和 View 。

1) 我不想使用 ADO.Net , 而我想使用 ORM使用 EntityFramework

2) 如果EntityFramework 6.1.3有能力调用Stored ProcsViews从现有数据库中,我如何解决错误(屏幕截图)?

实现此目标的最佳做法是什么?

最佳答案

希望我能正确理解您的问题。您在数据库中有现有的存储过程,例如 dbo.spGetSomeData,它返回包含某些字段的某些项目的列表,您需要通过 Web API 方法提供数据。

实现可能与以下内容有关。您可以定义一个 DbContext,例如:

public class MyDbContext : DbContext
{
}

并使用数据库的连接字符串定义appsettings.json

{
  "Data": {
    "DefaultConnection": {
      "ConnectionString": "Server=(localdb)\\mssqllocaldb;Database=MyDb;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
  }
}

您应该使用 Microsoft.Extensions.DependencyInjectionMyDbContext 添加到

public class Startup
{
    // property for holding configuration
    public IConfigurationRoot Configuration { get; set; }

    public Startup(IHostingEnvironment env)
    {
        // Set up configuration sources.
        var builder = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
            .AddEnvironmentVariables();
        // save the configuration in Configuration property
        Configuration = builder.Build();
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc()
            .AddJsonOptions(options => {
                options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            });

        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<MyDbContext>(options => {
                options.UseSqlServer(Configuration["ConnectionString"]);
            });
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        ...
    }
}

现在您可以按如下方式实现您的 WebApi 操作:

[Route("api/[controller]")]
public class MyController : Controller
{
    public MyDbContext _context { get; set; }

    public MyController([FromServices] MyDbContext context)
    {
        _context = context;
    }

    [HttpGet]
    public async IEnumerable<object> Get()
    {
        var returnObject = new List<dynamic>();

        using (var cmd = _context.Database.GetDbConnection().CreateCommand()) {
            cmd.CommandText = "exec dbo.spGetSomeData";
            cmd.CommandType = CommandType.StoredProcedure;
            // set some parameters of the stored procedure
            cmd.Parameters.Add(new SqlParameter("@someParam",
                SqlDbType.TinyInt) { Value = 1 });

            if (cmd.Connection.State != ConnectionState.Open)
                cmd.Connection.Open();

            var retObject = new List<dynamic>();
            using (var dataReader = await cmd.ExecuteReaderAsync())
            {
                while (await dataReader.ReadAsync())
                {
                    var dataRow = new ExpandoObject() as IDictionary<string, object>;
                    for (var iFiled = 0; iFiled < dataReader.FieldCount; iFiled++) {
                        // one can modify the next line to
                        //   if (dataReader.IsDBNull(iFiled))
                        //       dataRow.Add(dataReader.GetName(iFiled), dataReader[iFiled]);
                        // if one want don't fill the property for NULL
                        // returned from the database
                        dataRow.Add(
                            dataReader.GetName(iFiled),
                            dataReader.IsDBNull(iFiled) ? null : dataReader[iFiled] // use null instead of {}
                        );
                    }

                    retObject.Add((ExpandoObject)dataRow);
                }
            }
            return retObject;
        }
    }
}

上面的代码只是使用exec dbo.spGetSomeData 执行并使用dataRader 读取所有结果并保存在dynamic 对象中。如果您从 api/My 进行 $.ajax 调用,您将获得从 dbo.spGetSomeData 返回的数据,您可以直接在JavaScript 代码。上面的代码非常透明。 dbo.spGetSomeData 返回的数据集中的字段名称将是 JavaScript 代码中的属性名称。 您不需要以任何方式在 C# 代码中管理任何实体类。您的 C# 代码没有从存储过程返回的字段名称。因此,如果您要扩展/更改 dbo.spGetSomeData 的代码(重命名某些字段、添加新字段),您将只需要调整 JavaScript 代码,而不需要调整 C# 代码。

关于c# - 如何使用 EntityFramework 7 和 Asp.Net 5 调用 SQL 存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34745822/

相关文章:

sql - 返回包含最近 24 小时计数的记录

asp.net-core - 根据 Active Directory 对用户进行身份验证时存储 ASP.NET Core 授权声明的最佳实践?

asp.net-core-mvc - 如何在 ASP.net core mvc 中的响应上设置 Expires header

asp.net-mvc - 在 ASP.NET Core 1.0 中发布后修改 appsettings.Production.json 文件?

c# - 反射.Net : how to load dependencies?

c# - 结构图 - 如何在特定层中注册特定类型

c# - 获取不一致的可访问性错误

c# - 如何为unicode字符串的存储过程中的参数添加前缀 'N'

c# - Azure blob批量删除西里尔字符

java - 插入时如何忽略重复行