C# 从数据上下文获取存储过程:Linq到SQl

C# 从数据上下文获取存储过程:Linq到SQl,c#,.net,linq-to-sql,tdd,C#,.net,Linq To Sql,Tdd,我在SQL Server中有一个名为ParseXML的存储过程。我有一个使用LINQ到SQL的存储库模式。我需要从存储库层中调用存储过程。与GetTable方法不同,我们没有用于数据上下文的getStoredProcess方法。在这种情况下,我们如何调用存储过程 Dbml代码 [global::System.Data.Linq.Mapping.FunctionAttribute(Name="dbo.ParseXML")] public ISingleResult<ParseXML

我在SQL Server中有一个名为ParseXML的存储过程。我有一个使用LINQ到SQL的存储库模式。我需要从存储库层中调用存储过程。与GetTable方法不同,我们没有用于数据上下文的getStoredProcess方法。在这种情况下,我们如何调用存储过程

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));
    }
[global::System.Data.Linq.Mapping.FunctionAttribute(Name=“dbo.ParseXML”)]
公共ISingleResult ParseXML([global::System.Data.Linq.Mapping.ParameterAttribute(Name=“InputXML”,DbType=“Xml”)]System.Xml.Linq.XElement InputXML)
{
IExecuteResult=this.ExecuteMethodCall(this,((MethodInfo)(MethodInfo.GetCurrentMethod()),inputXML);
返回((IsingResult)(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();
    }

}

}
namespace RepositoryLayer
{
数据库存储库的公共接口
{
System.Data.Linq.DataContext上下文{get;set;}
列出GetAllAccountsForUser(int userID);
作废UpdateBankAccountUsingStoredProcedure();
}
公共类LijosSimpleBankRepository:ILijosBankRepository
{
public System.Data.Linq.DataContext上下文
{
得到;
设置
}
公共列表GetAllAccountsForUser(int userID)
{
IQueryable queryResultEntities=Context.GetTable()。其中(p=>p.AccountOwnerID==userID);
返回queryResultEntities.ToList();
}
使用StoredProcess()的公共虚拟无效更新银行帐户
{
//GetStroedProcedures();
}
}
}
参考:

  • C#包装器是自定义
    DataCcontext
    派生类的一部分。您可以这样称呼:

    public virtual void UpdateBankAccountUsingStoredProcedure()
    {
        var results = Context.ParseXML(...);
        ...
    }
    
    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);
         }
    
    }
    

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

    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);
    
    var inputXML=GetXML();
    动态上下文=上下文;
    var result=(ISingleResult)dynamicContext.ParseXML(inputXML);
    
    让存储库的任何调用者都知道某个特定方法调用是否会导致从文件、SQL语句、存储过程中读取文本,甚至只是让garden gnomes在文本终端上键入结果,这是SOC的一大突破

    为此,让您的
    上下文
    属性公开并没有什么帮助。使用存储库的全部意义在于使消费者免受持久性问题的影响

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

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

    public virtual void UpdateBankAccountUsingStoredProcedure()
    {
        var results = Context.ParseXML(...);
        ...
    }
    
    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);
         }
    
    }
    
    存储库中的公共接口 { 列出GetAllAccountsForUser(int userID); 作废UpdateBankAccount(/*参数转到此处*/); /*…其他查询方法等*/ } 公共类LijosBankRepository:ILijosBankRepository { 私有只读DataContext上下文{get;set;} 公共LijosBankRepository(DataContext ctx){…} 公共无效UpdateBankAccount(字符串inputXml) { ExecuteCommand(“ParseXML”,inputXml); } }
    这行不通。。。上下文是System.Data.Linq.DataContext的一种类型。ParseXML存储过程不是其中的一部分。我没有在intellisense for Context对象中看到ParseXML。您需要将属性
    Context
    更改为您创建的datacontext的类型,而不仅仅是
    System.Data.Linq.datacontext
    @ivowiblo我无法这样做,因为上下文将由存储库层的调用方决定。还有其他想法吗?显然,这个案子是必须的。如果您的具体存储库是针对特定的DatContext子类编程的,那么就可以了。事实上,必须这样才能工作。我收到编译错误:“System.Data.Linq.DataContext.ExecuteMethodCall(object,System.Reflection.MethodInfo,params object[])由于其保护级别而无法访问”。如何让它工作?嗯。当您的设计出现如此多的问题时,是时候开始审查设计了。那么,如果开发人员将定义要使用的datacontext,那么让开发人员放置datacontext而不知道它是否连接到具有ParseXML存储过程的数据库有意义吗?是否存在调用方将使用不同datacontext的场景?是。调用方可以使用任何数据上下文。您需要使用反射来调用该方法。这不是什么好事。@ivowiblo-我喜欢你把OP的问题写得很好。我确实相信有一种更简单的方法来实现OP的目标,它能回答OP问题的精神以及潜在的意图。@Lijo-那么这个解决方案对你有效,还是根本无效,或者有效,但不是你想要的?