Pra*_*sad 4 c# xml linq sql-server entity-framework-6
我需要使用Entity Framework,LINQ在我的asp.net mvc(C#)应用程序中查询SQL中的XML数据.
我有一个XMLValue
包含数据的列
<MetaData>
<Reviews>1</Reviews>
<Rating>1</Rating>
</MetaData>
Run Code Online (Sandbox Code Playgroud)
我需要从xml中获得所有Customers
拥有Rating
1的人.我已经提到了这个stackoverflow帖子,我无法实现它.
我添加了SQL函数并将其添加到我的edmx:
CREATE FUNCTION [dbo].[FilterCustomersByRating]
(@Rating int)
RETURNS TABLE
AS
RETURN
SELECT XMLTest.*
FROM XMLTest
CROSS APPLY XMLValue.nodes('//MetaData') N(C)
where N.C.value('Rating[1]', 'int')=@Rating
GO
Run Code Online (Sandbox Code Playgroud)
以及DB功能:
[DbFunction("XMLDBModel.Store", "FilterCustomersByRating")]
public static IQueryable<XMLTest> MyXmlHelper(int rating)
{
throw new NotImplementedException("You can only call this function in a LINQ query");
}
Run Code Online (Sandbox Code Playgroud)
下面是我在帖子中完全尝试的linq查询,但是无法使用该函数并且它会抛出错误.
var _dbCustomers = (from x in _context.XMLTests
where MyXmlHelper(1).Where(xh=> xh.XMLValue.Contains("1"))
select x);
Run Code Online (Sandbox Code Playgroud)
错误:
Cannot implicitly convert type 'System.Linq.IQueryable<XMLTest>' to 'bool
Run Code Online (Sandbox Code Playgroud)
如果我用户Any(),我有以下错误:
var _dbCustomers = (from x in _context.XMLTests
where MyXmlHelper(1).Any(xh => xh.XMLValue.Contains("1"))
select x);
Run Code Online (Sandbox Code Playgroud)
错误:
The specified method 'System.Linq.IQueryable`1[XMLTest] MyXmlHelper(Int32)' on the type 'CustomerRepository' cannot be translated into a LINQ to Entities store expression because its return type does not match the return type of the function specified by its DbFunction attribute.
Run Code Online (Sandbox Code Playgroud)
有人可以建议如何实现这一目标吗?
我认为问题是由存根函数的返回类型引起的.
你能检查一下FilterCustomersByRating
DbContext中你的方法的返回类型吗?我认为不应该这样XMLTest
.它应该类似于下面的代码:
[EdmFunction("TestingDbEntities", "FilterCustomersByRating")]
public virtual IQueryable<FilterCustomersByRating_Result> FilterCustomersByRating(Nullable<int> rating)
{
var ratingParameter = rating.HasValue ?
new ObjectParameter("Rating", rating) :
new ObjectParameter("Rating", typeof(int));
return ((IObjectContextAdapter)this)
.ObjectContext
.CreateQuery<FilterCustomersByRating_Result>("[TestingEntities]
.[FilterCustomersByRating](@Rating)", ratingParameter);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,存根函数的返回类型将是类型FilterCustomersByRating_Result
,当您将FilterCustomersByRating
表值函数添加到edmx文件时,该类是自动生成的类.
CREATE FUNCTION [dbo].[FilterCustomersByRating]
(@Rating int)
RETURNS TABLE
AS
RETURN
SELECT XMLTest.*
FROM XMLTest
CROSS APPLY XMLValue.nodes('//MetaData') N(C)
where N.C.value('Rating[1]', 'int')=@Rating
GO
Run Code Online (Sandbox Code Playgroud)
考虑到这一点,你的存根函数应该返回IQueryable<FilterCustomersByRating_Result>
ie
[EdmFunction("TestingDbEntities", "FilterCustomersByRating")]
public static IQueryable<FilterCustomersByRating_Result> MyXmlHelper(int rating)
{
throw new NotImplementedException("You can only call this function in a LINQ query");
}
Run Code Online (Sandbox Code Playgroud)
你可以使用它,如下所示:
var dbCustomers = (from x in _context.XMLTests
where MyXmlHelper(1).Any(xh => xh.XMLValue.Contains("1"))
select x);
Run Code Online (Sandbox Code Playgroud)
请注意,虽然这将工作,它将返回所有Customers
.您可能需要修改FilterCustomersByRating
函数以接受CustomerID
和rating
.
试试看.
编辑
除了上面的,定义时MyXmlHelper
EdmFunction,确保的拼写FunctionName
和NamespaceName
是正确的.在我的例子中,FunctionName
is FilterCustomersByRating
和NamespaceName
是TestingEntities
匹配自动生成的DBContext类中的值.
// </auto-generated code>
public partial class TestingEntities : DbContext
{
public TestingEntities()
: base("name=TestingEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<XMLTest> XMLTests { get; set; }
[EdmFunction("TestingEntities", "FilterCustomersByRating")]
public virtual IQueryable<FilterCustomersByRating_Result> FilterCustomersByRating(Nullable<int> rating)
{
var ratingParameter = rating.HasValue ?
new ObjectParameter("Rating", rating) :
new ObjectParameter("Rating", typeof(int));
return ((IObjectContextAdapter)this)
.ObjectContext
.CreateQuery<FilterCustomersByRating_Result>("[TestingEntities]
.[FilterCustomersByRating](@Rating)", ratingParameter);
}
}
Run Code Online (Sandbox Code Playgroud)