C# 从数据上下文获取存储过程:Linq到SQl
我在SQL Server中有一个名为ParseXML的存储过程。我有一个使用LINQ到SQL的存储库模式。我需要从存储库层中调用存储过程。与GetTable方法不同,我们没有用于数据上下文的getStoredProcess方法。在这种情况下,我们如何调用存储过程 Dbml代码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
[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-那么这个解决方案对你有效,还是根本无效,或者有效,但不是你想要的?