I need to use Entity Framework, LINQ to query the XML data from the SQL in my asp.net mvc(C#) application.
I have a column XMLValue
with data
<MetaData>
<Reviews>1</Reviews>
<Rating>1</Rating>
</MetaData>
I need to get all the Customers
who have a Rating
of 1 from the xml. I have referred to this stackoverflow post and I am not able to achieve it.
I have added the SQL function and added it to my 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
And the following DB function:
[DbFunction("XMLDBModel.Store", "FilterCustomersByRating")]
public static IQueryable<XMLTest> MyXmlHelper(int rating)
{
throw new NotImplementedException("You can only call this function in a LINQ query");
}
Below is the linq query which I tried exactly as in the post, but not able to use the function and it throws error.
var _dbCustomers = (from x in _context.XMLTests
where MyXmlHelper(1).Where(xh=> xh.XMLValue.Contains("1"))
select x);
Error:
Cannot implicitly convert type 'System.Linq.IQueryable<XMLTest>' to 'bool
If I user Any(), I have the following error:
var _dbCustomers = (from x in _context.XMLTests
where MyXmlHelper(1).Any(xh => xh.XMLValue.Contains("1"))
select x);
Error:
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.
Can someone suggest on how to achieve this please?
First error
where
clause in your queries needs to evaluate to abool
value.MyXmlHelper(1).Where(xh=> xh.XMLValue.Contains("1"))
will give a record of typeSystem.Linq.IQueryable<XMLTest>
and notbool
. You need to come up with a expression which will return abool
value.Second error
Same is applicable to second error - change your where clause to get
bool
value from the expression.Change "=" to "LIKE". Don't know what N(C) is, cross apply, or N.C.value(), but using = instead of LIKE often gives me trouble. Its trying to cross evaluate ints/bools with strings, and for strings like "1" you should use LIKE
I think the problem is caused by the return type of your stub function.
Can you check what the return type for your
FilterCustomersByRating
method is in your DbContext? I don't think it should beXMLTest
. It should look similar to the code below:In this case, the return type of the stub function would be of type
FilterCustomersByRating_Result
which is class auto-generated when you add theFilterCustomersByRating
Table-valued function to your edmx file.With this in mind your stub function should be return
IQueryable<FilterCustomersByRating_Result>
i.e.you can the use it as shown below:
Please note that while this will work it will return all
Customers
. You might need to modify theFilterCustomersByRating
function to accept theCustomerID
andrating
.Give it a try.
EDIT
In addition to the above, when defining the
MyXmlHelper
EdmFunction, make sure that the spelling of theFunctionName
andNamespaceName
is correct. In my case, theFunctionName
isFilterCustomersByRating
andNamespaceName
isTestingEntities
which match the values in the auto-generated DBContext class.