从数据上下文中获取存储过程:Linq to SQL

3
我在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. 多个UnitOfWorks、ISession和repositories
3个回答

2
您可以使用反射调用方法,类似于以下示例:
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[])' 由于其保护级别而无法访问"。如何解决? - LCJ
3
当你开始遇到很多与设计有关的问题时,就是开始检查设计的时候了。因此,如果开发人员要定义使用哪个数据上下文,让开发人员放置一个数据上下文而不知道它是否连接到具有ParseXML存储过程的数据库,这是否有意义?是否存在调用者将使用不同数据上下文的情况? - Ivo
是的。调用者可以使用任何数据上下文。 - LCJ
1
你需要使用反射来调用那些方法。这不是一个好的做法。 - Ivo
1
@ivowiblo - 我很喜欢你对原帖问题的回答,做得非常好。我相信有一种更简单的方法可以实现原帖的目标,既能回答原帖问题的本质,也能满足其潜在意图。 - Josh E

2
“SOC”指的是“单一职责原则”,对于您的存储库的任何调用者了解特定方法调用是否会从文件中读取文本、SQL语句、存储过程或仅在文本终端上键入结果,这是一个相当大的破坏。为此,使您的Context属性成为公共属性并不会有所帮助。使用存储库的整个重点是让消费者免于持久性问题的干扰!由于您似乎非常需要避免使用自定义类型的Context,因此您最好直接发出旧式的SQL语句来执行sproc,以避免诸多麻烦。请考虑重构您的接口和逻辑,使其更像下面这样:”
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 - 这个解决方案对你有用吗?还是根本不行?或者它能够工作但不是你想要的? - Josh E

1
C#包装器是您自定义的DataCcontext派生类的一部分。您可以这样调用:
public virtual void UpdateBankAccountUsingStoredProcedure()
{
    var results = Context.ParseXML(...);
    ...
}

这样行不通...Context是System.Data.Linq.DataContext类型的一种。ParseXML存储过程不属于它。我在Context对象的智能感知中没有看到ParseXML。 - LCJ
你需要将属性 Context 更改为你所创建的 datacontext 类型,而不仅仅是 System.Data.Linq.DataContext - Ivo
@ivowiblo 我做不到,因为 Context 将由存储库层的调用者决定。还有其他想法吗? - LCJ
必须使用案例,这一点显而易见。如果您的具体存储库是针对特定 DatContext 子类编程的,则可以使用。事实上,为了使其正常工作,必须这样做。 - bluevector

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接