【问题标题】:ASP.NET MVC: Best Way To Call Stored ProcedureASP.NET MVC:调用存储过程的最佳方式
【发布时间】:2010-11-23 19:30:50
【问题描述】:

我正在尝试确定调用存储过程的最佳方式。

我是 ASP.NET MVC 的新手,我已经阅读了很多关于 Linq to SQL 和实体框架以及存储库模式的内容。老实说,我很难理解 L2S 和 EF 之间的真正区别......但我想确保我在应用程序中构建的内容是正确的。

目前,我需要正确调用存储过程:a) 保存一些用户信息并获得响应,b) 获取产品目录的一些信息。

到目前为止,我已经创建了一个 Linq to SQL .dbml 文件,从服务器资源管理器中选择了 sotred 过程并将该实例拖到 .dbml 中。我目前正在这样调用存储过程:

MyLinqModel _db = new MyLinqModel();
_db.MyStoredProcedure(args);

我知道有更多的参与...而且我在我的控制器中这样做,我知道这不是一个好习惯。

有人能认出我的问题吗?

【问题讨论】:

    标签: asp.net-mvc linq-to-sql stored-procedures


    【解决方案1】:

    如果您想要做的只是调用存储过程,那么 LINQ 和 EF 可能有点过头了。

    我使用企业库,但 ADO.NET 也可以正常工作。

    this tutorial

    简单地说(从引用的文章中无耻地复制和粘贴):

        SqlConnection conn = null;
        SqlDataReader rdr  = null;
    
        // typically obtained from user
        // input, but we take a short cut
        string custId = "FURIB";
    
        Console.WriteLine("\nCustomer Order History:\n");
    
            // create and open a connection object
            conn = new SqlConnection("Server=(local);DataBase=Northwind; Integrated Security=SSPI");
            conn.Open();
    
            // 1.  create a command object identifying
            //     the stored procedure
            SqlCommand cmd  = new SqlCommand(
                "CustOrderHist", conn);
    
            // 2. set the command object so it knows
            //    to execute a stored procedure
            cmd.CommandType = CommandType.StoredProcedure;
    
            // 3. add parameter to command, which
            //    will be passed to the stored procedure
            cmd.Parameters.Add(
                new SqlParameter("@CustomerID", custId));
    
            // execute the command
            rdr = cmd.ExecuteReader();
    
            // iterate through results, printing each to console
            while (rdr.Read())
            {
                Console.WriteLine(
                    "Product: {0,-35} Total: {1,2}",
                    rdr["ProductName"],
                    rdr["Total"]);
            }
        }
    

    更新

    我错过了您说您在控制器中执行此操作的部分。

    不,这不是正确的做法。

    您的控制器实际上应该只参与编排视图构建。创建一个单独的类库,称为“数据访问层”或不太通用的东西,并创建一个处理调用存储过程、从结果创建对象等的类。关于如何处理有很多意见,但也许最常见的是:

    View
    |
    Controller
    |
    Business Logic
    |
    Data Access Layer
       |--- SQL (Stored procs)
               -Tables
               -Views
               -etc.
       |--- Alternate data sources
               -Web services
               -Text/XML files
               -blah blah blah.
    

    MSDN has a decent tutorial on the topic.

    【讨论】:

    • +1 用于简单访问模型 ADO.NET,而 API 上的丑陋仍然是王道。这不足为奇,因为基本上所有其他单一的数据访问技术都归结为 ADO.NET。
    • 是的。认识一个有开发人员的人认为企业库比 ado.net 更快。我喜欢企业库,但 DAAB 包装了 ado.net,所以声称它更快是很愚蠢的。了解你的工具,伙计们!
    【解决方案2】:

    试试这个:

    阅读:

    var authors = context.Database.SqlQuery<Author>("usp_GetAuthorByName @AuthorName", 
    new SqlParameter("@AuthorName", "author"));
    

    更新:

    var affectedRows = context.Database.ExecuteSqlCommand
    ("usp_CreateAuthor @AuthorName = {0}, @Email= {1}", 
    "author", "email");
    

    来自这个链接:http://www.dotnetthoughts.net/how-to-execute-a-stored-procedure-with-entity-framework-code-first/

    我会使用 David Lively 提到的框架,而不是在控制器中使用例程。只需将结果作为 IEnumerable&lt;blah&gt; 从单独的存储库类中的函数传回以进行编辑,如果更新成功则传回布尔值以进行更新。

    【讨论】:

      【解决方案3】:

      LINQ to SQL 和 ADO.NET EF 将读取存储的过程附加到数据/对象上下文类,您可以使用它来处理其各种实体。对于创建、更新和删除,您可以创建一个映射模型生成的实体属性的 proc,并使用实体映射窗口(现在忘记确切名称),您可以使用 proc 参数映射实体字段.因此,假设您有一个客户表,EF 生成一个客户实体,您可以在尝试更新/插入/删除时将 proc 参数映射到客户实体的属性。

      现在,您可以将 CUD 过程映射到函数,但我不知道所有影响;我喜欢我刚才提到的最好的方式。

      HTH。

      【讨论】:

        【解决方案4】:

        我常见的模式是通过依赖注入将存储库接口传递给您的控制器。选择使用哪种持久性/orm 技术实际上是另一个问题,与您使用 MVC 的事实无关。使用存储库模式和对抽象(接口)进行编码可以通过模拟存储库来轻松测试您的应用程序。

        我认为您还应该尝试使用尽可能少的存储过程。这意味着您可以更轻松地单独测试您的逻辑(单元测试),而无需连接到数据库。我强烈建议您查看 NHibernate。学习曲线相当陡峭,但您可以完全控制映射和配置。显然,出于性能原因,您需要存储过程,但主要使用 ORM 是非常有益的。

        【讨论】:

        • 应在适当的地方使用存储过程,而不是“尽可能少”。 DBA 第一次来找我告诉我她解决了一个我什至不知道存在的 SQL 问题时,足以让我相信这一点。此外,能够对您的 SQL 执行编译时检查,以及将您的数据层抽象为可由多种语言/平台的多个应用程序使用的组件,这是一个不容忽视的好处。我已经看到项目崩溃了,因为开发人员决定切换语言并且不得不重写每个怪异的查询,因为它们是嵌入的
        • @David,同意...这是其中一种很好的情况。
        • 我知道这是从 2010 年开始的,但我最近看了 NHibernate 一次 - 甚至无法编译!它现在也已经过时了,因为他们的 1.1(我记得是最新的)版本与 .NET 3.5 不兼容,更不用说 4.0 了。需要大幅提升的第三方实用程序也不会受到试图推出项目的经理的欢迎(并且在您离开下一份合同时会担心)。
        • 感谢单元测试的存储库/依赖注入方法,所以我不会敲你,因为它基本上是 David Lively 提到的,但是当你必须添加功能时它确实增加了复杂性在业务层中只是为了访问存储库,而您并不真正需要它,因为您没有进行全面的自动化单元测试。
        【解决方案5】:

        我无法想象您的目标是能够调用存储过程。对我来说,这听起来好像您需要忘记存储过程并使用 Linq to Sql。我说 L2S 是因为 EF 要学习的东西要多得多,在这种情况下不需要。

        【讨论】:

        • 为什么你认为他的目标不是调用存储过程,而他明确表示它是?
        猜你喜欢
        • 1970-01-01
        • 2012-06-11
        • 2013-09-19
        • 1970-01-01
        • 2011-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多