【问题标题】:Get Stored Procedure from Data Context : Linq to SQl从数据上下文获取存储过程:Linq 到 SQl
【发布时间】:2012-07-12 14:08:09
【问题描述】:

我在 SQL Server 中有一个名为 ParseXML 的存储过程。我有一个使用 LINQ to SQL 的存储库模式。我需要从存储库层调用存储过程。与 GetTable 方法不同,我们没有用于数据上下文的 GetStoredProcedure 方法。这种场景下怎么调用存储过程呢?

Dbml 代码

[global::System.Data.Linq.Mapping.FunctionAttribute(Name="dbo.ParseXML")]

    public ISingleResult<ParseXMLResult> ParseXML([global::System.Data.Linq.Mapping.ParameterAttribute(Name="InputXML", DbType="Xml")] System.Xml.Linq.XElement inputXML)
    {
        IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), inputXML);
        return ((ISingleResult<ParseXMLResult>)(result.ReturnValue));
    }

存储层

namespace RepositoryLayer
{
public interface ILijosBankRepository
{
    System.Data.Linq.DataContext Context { get; set; }
    List<DBML_Project.BankAccount> GetAllAccountsForUser(int userID);
    void UpdateBankAccountUsingStoredProcedure();

}

public class LijosSimpleBankRepository : ILijosBankRepository
{
    public System.Data.Linq.DataContext Context
    {
        get;
        set;
    }


    public List<DBML_Project.BankAccount> GetAllAccountsForUser(int userID)
    {
        IQueryable<DBML_Project.BankAccount> queryResultEntities = Context.GetTable<DBML_Project.BankAccount>().Where(p => p.AccountOwnerID == userID);
        return queryResultEntities.ToList();
    }


    public virtual void UpdateBankAccountUsingStoredProcedure()
    {
        //Context.GetStroedProcedures();
    }

}

}

参考:

  1. Multiple UnitOfWorks, ISession and repositories

【问题讨论】:

    标签: c# .net linq-to-sql tdd


    【解决方案1】:

    你可以这样做,使用反射调用方法:

    var inputXML = GetXML(); 
    
    var method = Context.GetType().GetMethod("ParseXML");
    
    if(method == null) throw new InvalidOperationException("Defined DataContext does not have method ParseXML");
    
    var result = method.Invoke(Context, new object[]{ inputXML });
    

    如果你使用的是 c# 4.0,你可以这样做:

    var inputXML = GetXML(); 
    
    dynamic dynamicContext = Context;
    
    var result = (ISingleResult<ParseXMLResult>)dynamicContext.ParseXML(inputXML);
    

    【讨论】:

    • 我收到编译错误:“'System.Data.Linq.DataContext.ExecuteMethodCall(object, System.Reflection.MethodInfo, params object[])' 由于其保护级别而无法访问”。如何让它发挥作用?
    • 嗯。当你开始对你的设计有这么多问题时,是时候开始审查设计了。因此,如果开发人员将定义要使用的数据上下文,让开发人员放置一个数据上下文而不知道它是否使用 ParseXML 存储过程连接到数据库是否有意义?有没有调用者会使用不同数据上下文的场景?
    • 是的。调用者可以使用任何数据上下文。
    • 您需要使用反射来调用这些方法。这不是什么好事。
    • @ivowiblo - 我喜欢你很好地解决了 OP 问题的信。我确实相信有一种更简单的方法来完成 OP 的目标,以回答 OP 的问题的精神和潜在的意图。
    【解决方案2】:

    让存储库的任何调用者都知道特定方法调用是否会导致从文件、SQL 语句、存储过程中读取文本,甚至只是花园侏儒在文本上键入结果,这对 SOC 来说是一个相当大的突破终端。

    为此,将您的 Context 属性公开也无济于事。使用存储库的全部意义在于使消费者免受持久性问题的影响!

    由于您似乎非常需要避免使用自定义类型的 Context,因此您可以省去很多麻烦,只需发出一个直接的老式 SQL 语句来执行您的存储过程。

    考虑重构您的界面和逻辑,使其看起来更像这样:

    public interface ILijosBankRepository
    {
        List<DBML_Project.BankAccount> GetAllAccountsForUser(int userID);
        void UpdateBankAccount(/* params go here */);
        /* ...other query methods, etc... */
    
    }
    public class LijosBankRepository : ILijosBankRepository
    {
         private readonly DataContext context { get; set;}
         public LijosBankRepository(DataContext ctx) { ... }
    
         public void UpdateBankAccount(string inputXml)
         {
              context.ExecuteCommand("ParseXML", inputXml);
         }
    
    }
    

    【讨论】:

    • @Lijo - 这个解决方案是否适合您,或者根本不适合,或者它有效但不是您想要的?
    【解决方案3】:

    C# 包装器是您的自定义DataCcontext 派生类的一部分。你会这样调用:

    public virtual void UpdateBankAccountUsingStoredProcedure()
    {
        var results = Context.ParseXML(...);
        ...
    }
    

    【讨论】:

    • 这行不通... Context 是 System.Data.Linq.DataContext 的一种。 ParseXML 存储过程不是其中的一部分。我没有在 Context 对象的智能感知中看到 ParseXML。
    • 您需要将属性Context 更改为您创建的数据上下文的类型,而不仅仅是System.Data.Linq.DataContext
    • @ivowiblo 我不能这样做,因为上下文将由存储库层的调用者决定。还有其他想法吗?
    • 显然是必须的。如果您的具体存储库针对特定的 DatContext 子类进行编程,则可以。事实上,它必须是为了让它起作用。
    猜你喜欢
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 2013-09-28
    • 1970-01-01
    相关资源
    最近更新 更多