Using a flag in an Entity Framework Where clause - entity-framework

I have a class (built by EF from my database) that has a field that is a flag. The field is stored in the database as an int in a column named CategoryEnum. I have an enum that specifies the permissible values of the flag:
[Flags]
public enum RuleCategories
{
None = 0x0000,
ApplicantBased = 0x0001,
LocationBased = 0x0002,
PolicyBased = 0x0004,
PropertyBased = 0x0008
}
When I try to retrieve the objects using LINQ to Entities
var allRules = from r in context.Rules
where ((r.CategoryEnum & (int)categories) != 0)
select r;
I get this error:
Unable to create a constant value of type 'Closure type'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.
or, if I try to cast the entity value to the enum
var allRules = from r in context.Rules
where (((RuleCategories)r.CategoryEnum & categories) != 0)
select r;
I get a different error:
Unable to cast the type 'System.Int32' to type RuleCategories'. LINQ to Entities only supports casting Entity Data Model primitive types.
How do I select entities based on a flag?
Thanks

I am going to guess and say that you are using the good old EF 3.5. This works without problems with EF 4.0 in VS2010. There is a problem with the 3.5 version, however, and you will have to use a workaround. Cast the categories variable to int before the query, and then use your int variable inside the query itself:
int preCastCategories = (int)categories;
var allRules = from r in context.Rules
where ((r.CategoryEnum & preCastCategories) != 0)
select r;

Related

Conditionally add query operator on properties defined in non-EDM base type, if inheriting

(C# code at end of question)
I have the following inheritance chain:
PreRecord <- Record <- (multiple entity types)
Record declares a property ID As Integer.
PreRecord and Record are not EDM types, and do not correspond to tables in the database.
I have a method that takes a generic parameter constrained to PreRecord and builds an EF query with the generic parameter as the element type. At runtime, in the event that T inherits not just from PreRecord but from Record, I would like add an OrderBy operator on ID:
'Sample 1
Function GetQuery(Of T As PreRecord)(row As T) As IQueryable(Of T)
Dim dcx = New MyDbContext
Dim qry = dcx.Set(Of T).AsQueryable
If TypeOf row Is RecordBase Then
'modify/rewrite the query here
End If
Return qry
End Function
If the parameter constraint were to Record I would have no problem applying query operators that use the ID property. How can I make use of a different (narrowing) generic constraint mid-method and still return an IQueryable(Of T) / IQueryable<T>, where T is still constrained to PreRecord?
I tried this:
'Sample 2
qry = dcx.Set(Of T).Cast(Of Record).OrderBy(Function(x) x.ID).Cast(Of PreRecord)()
which doesn't work:
LINQ to Entities only supports casting EDM primitive or enumeration types.
C# equivalent:
//Sample 1
public IQueryable<T> GetQuery<T>(T row) where T : PreRecord {
var dcx = new MyDbContext();
var qry = dcx.Set<T>.AsQueryable();
if (row is RecordBase) {
//modify/rewrite the query here
}
return qry;
}
and this doesn't work:
//Sample 2
qry = dcx.Set<T>.Cast<Record>.OrderBy(x => x.ID).Cast<PreRecord>()
The problem here is the fact that compiler checks queries already at compile time and PreRecord class does not have ID property. We cannot use simply Cast, because when it is used in definition of the query parser tries to convert it to sql - but there is no such thing that exists in sql. Sql supports only conversion of one column type to another - so on the .NET side it is supported only for primitive and enum types. To overcome compiler query checking we may use Expression class to build dynamic queries:
ParameterExpression e = Expression.Parameter(typeof(Record));
Expression body = Expression.Property(e, "ID");
Expression<Func<PreRecord, int>> orderByExpression = Expression.Lambda<Func<PreRecord, int>>(body, e);
And use your expression in the query:
qry = dcx.Set<T>.OrderBy(orderByExpression);
This way your linq query will not be validated during compile time but execution time. Here I assumed ID is of type int, if the type is different change it accordingly.

How to use composite types as parameters with Npgsql and Telerik OpenAccess

I have a PostgreSQL 9.1 stored procedure:
FUNCTION g_savedx(_cpatient text, o view_dx, n view_dx) RETURNS void
where view_dx is a table. If I understand the PostgreSQL manual correctly, when used as a parameter to a stored procedure, only the TYPE is used. Hence, the table will be seen here as if I used CREATE TYPE.
Now Telerik EntityFramework compiles the following definition in the Domain Model:
public int SaveDx(string cpatient, Object o, Object n)
{
OAParameter parameterCpatient = new OAParameter();
parameterCpatient.ParameterName = "_cpatient";
parameterCpatient.Size = -1;
if(cpatient != null)
{
parameterCpatient.Value = cpatient;
}
else
{
parameterCpatient.DbType = DbType.String;
parameterCpatient.Value = DBNull.Value;
}
OAParameter parameterO = new OAParameter();
parameterO.ParameterName = "o";
parameterO.Value = o;
OAParameter parameterN = new OAParameter();
parameterN.ParameterName = "n";
parameterN.Value = n;
int queryResult = this.ExecuteNonQuery("SELECT * FROM \"public\".\"g_savedx\"(_cpatient, o, n)", CommandType.Text, parameterCpatient, parameterO, parameterN);
return queryResult;
}
Upon compiling, Telerik complains with:
The specified clr type 'Object' is not valid for the parameter n of the procedure 'g_savedx'.
Attempts at "Fixing" the error by telling Telerik to use CLR Type System.Object consistently fail.
This ultimately is leading me to suspect that Telerik is using Npgsql as the interface to the PostgreSQL database and that Telerik is looking for a DBType of View_dx as reported by the PostgreSQL database. This type, ofcourse, does not exist in either the NpgsqlDbType enumerations nor System.Data DbType enumeration.
Somebody please tell me I'm wrong! Or, how to fix this, as I'd really like to use the PostgreSQL stored procedure with a composite type as a parameter.
Any help is most appreciated.

Unable to create a constant value of type 'System.Object'. Only primitive types ('such as Int32, String, and Guid') are supported in this context

I'm using MVC and Entity Framework. I've created a class in my model folder with this code below. I keep getting the error message above with both queries below. I know there is a known issue on referencing non-scalar variables, but I'm not sure how to implement a workaround:
http://msdn.microsoft.com/en-us/library/bb896317.aspx#Y1442
private MovieLibraryDBEntities movieLibraryDBEntitiesContext;
public int getNumberOfEntriesReserved()
{
return (from m in movieLibraryDBEntitiesContext.Movies
where m.CheckedOut.Equals(1)
select m).Count();
//return movieLibraryDBEntitiesContext.Movies
// .Where(e => e.CheckedOut.Equals(1))
// .Select (e => e.Title).Count();
}
You cannot use m.CheckedOut.Equals(1) in linq-to-entities query. Use m.CheckedOut == 1 but CheckedOut must be integer.
This is an older question. I had the same problem when trying to filter a nullable column using the IQueryable interface. I solved the problem by first checking to see if the object had a value and then checking the value.
widgets = widgets.Where(x => x.ID.HasValue.Equals(true) && x.ID.Value.Equals(widgetID));
same issue using Any()
i had to change my where clause to search on primitive types, for me int
so this
where order.User == user
becomes this
where order.User.UserId == user.UserId
There is a blog post explaining the quirk.

EF1: Filtering derived types of entity class using .OfType<> by passing a string value

I have a situation where I'm trying to filter a LINQ select using a derived sub class.
ctx.BaseEntity.OfType<SubClass>() - this works fine.
However I'd like to do this using a string value instead. I've come across a performance barrier when I have lots (>20) Sub Classes and selecting an Entity without using OfType just isn't an option. I have a generic UI that renders from the base class, so I don't know what Class Type will be returned at compile time.
So what I'd like to do is this:
Perform a projected Select where I
return just the SubClassType from
the database
Perform a second select
using this value as the OfType to
only select the relevant related
entity from the database (No mass
unions generated)
int id = 1;
var classType = (from c in ctx.BaseClass.Include("ClassType")
where c.id == id
select new
{
c.ClassType.TypeName
}).First();
BaseClass caseQuery = ctx.BaseClass.OfType<classType.TypeName>()
.Include("ClassType")
.Include("ChildEntity1")
.Include("ChildEntity2")
.Where(x => x.id== id);
But obviously this won't work because OfType requires a Type and not a string.
Any ideas on how I can achieve this?
Update:
As a side note to the original question, it turns out that the moment you project a query that uses a Navigation Property - it builds the monster SQL too, so I've ended up using a stored procedure to populate my ClassType entity from the BaseClass Id.
So I've just got it to work using eSQL, which I'd never used before. I've posted the code here just in case it helps someone. Has anyone else got a more strongly typed solution they can think of?
BaseClass caseQuery = ctx.BaseClass.CreateQuery<BaseClass>("SELECT VALUE c FROM OFTYPE(Entities.[BaseClass],namespace.[" + classType.TypeName + "]) as c")
.Include("ClassType")
.Include("ChildEntity1")
.Include("ChildEntity2")
.Where(x => x.id== id).FirstOrDefault();
To answer the headline question about calling OfType with a string / runtime type, you can do the following:
// Get the type, assuming the derived type is defined in the same assembly
// as the base class and you have the type name as a string
var typeToFilter = typeof(BaseClass)
.Assembly
.GetType("Namespace." + derivedTypeName);
// The use reflection to get the OfType method and call it directly
MethodInfo ofType = typeof(Queryable).GetMethod("OfType");
MethodInfo ofTypeGeneric = method.MakeGenericMethod(new Type[] { typeToFilter });
var result = (IQueryable<Equipment>)generic.Invoke(null, new object[] { equipment });
Combine this with your stored procedure to get the class name and you (should?) avoid the massive join - I don't have table-per-type implementation to play with so I can't test.

int to string in Entity Framework

How do you convert an int to a string in Link to EF?
The clr cant imagine casting an int to a string and Entity framework cant figure out what SQL snippet to translate .ToString() into.
So how do you write a linq statement that returns a string instead of an int?
Sadly EF does not know how to convert .ToString(). You must use the embedded function SqlFunctions.StringConvert: http://msdn.microsoft.com/en-us/library/dd466292.aspx
Also there is no overload for int so you must typecast to double :-(
var vendors =
from v in Vendors
select new
{
Code = SqlFunctions.StringConvert((double)v.VendorId)
};