Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
168 views
in Technique[技术] by (71.8m points)

c# - Entity Framework/Linq EXpression converting from string to int

I have an Expression like so:

var values = Enumerable.Range(1,2);

return message => message.Properties.Any(
    p => p.Key == name 
    && int.Parse(p.Value) >= values[0] 
    && int.Parse(p.Value) <= values[1]);

This compiles fine but when it hits the database it throws the exception 'LINQ to Entities does not recognize the method 'Int32 Parse(System.String)' method, and this method cannot be translated into a store expression '

If I don't do the parse and have values be a string[] I can't then use the >= and <= operators on strings.

p.Value is a string which holds various values but in this case it is int

Is there a way I can query the database to do this sort of between statement?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As much as I hate this answer, the actual answer is you can't do it easily. It will be a real pain. I've seen lots of wrong answers and lots of answers with people saying you should just have your database fields be the correct type in the first place, which is not helpful.

Your question is similar to this question on MSDN.

There are several possibilities depending on what sort of EF you are using.

1. You are using EDMX files.

(Not code first or reverse engineered code first).

You can use something like this (from this answer):

[EdmFunction("PlusDomain", "ParseDouble")]
public static double ParseDouble(string stringvalue)
{
    // This method exists for use in LINQ queries,
    // as a stub that will be converted to a SQL CAST statement.
    return System.Double.Parse(stringvalue);
}

and map it in your EDMX like this:

<Function Name="ParseDouble" ReturnType="Edm.Double">
    <Parameter Name="stringvalue" Type="Edm.String" />
    <DefiningExpression>
        cast(stringvalue as Edm.Double)
    </DefiningExpression>
</Function>

2. If you are using code first in EF >= 4.1.

You are screwed. Microsoft didn't see fit to add any such function to SqlFunctions. The best you can hope for is to add a scalar SQL function into your database and (maybe) try to map it into your context. Microsoft didn't see any point in doing anything like this in code first. Fortunately they didn't totally block such things either. The Fluent API is powerful.

You can call the functions or stored procedures like this (reference):

var outParam = new SqlParameter("overHours", SqlDbType.Int);
outParam.Direction = ParameterDirection.Output;

Or like this (reference):

var data = context.Database.ExecuteSqlCommand("dbo.sp_getNumberJobs @overHours OUT", outParam);
int numJobs = (int)outParam.Value;

But to make them actually integrate into LINQ to Entities, you need something like CodeFirstFunctions, by using the EntityFramework.CodeFirstStoreFunctions NuGet package. It maps the SQL functions into the context, but it uses an external library only made for .NET 4.5 (see here).

Instead, you can attempt to do the same thing manually like in this question.

The quicker solution I've settled on for my needs is to just create a view with the converted types. This avoids the whole problem.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...