I'm wondering how to get the query below to work:
IQueryable<TypeA> data = ...;
data = data.OrderBy(x => ((TypeB)x.RelatedObject).Value);
The error I get is:
The specified type member 'RelatedObject' is not supported in LINQ to
Entities. Only initializers, entity members, and entity navigation
properties are supported.
I'm very new to C#, I think this is a compile problem because I know RelatedObject is of TypeB.
Thanks!
Apparently, Entity Framework does not know (enough) about the relation between TypeA and TypeB. If you can define it as a navigation property, that would solve your problem.
If that is not possible, inserting .AsEnumerable() should work:
data.AsEnumerable().OrderBy(x => ((TypeB)x.RelatedObject).Value);
What this will do, is having 'normal' LINQ performing the ordering, instead of the database (with an ORDER BY clause in the SQL query). Note that it returns an IEnumerable<TypeA> instead of an IQueryable<TypeA> - depending on what you do with this variable, this might cause more records to be loaded into memory than strictly necessary.
If you know that you're only getting one specific type, you should be able to do something like this, assuming that EF knows about the inheritance.
IQueryable<TypeA> data = ...;
data = data.OfType<TypeB>().OrderBy(x => (x.RelatedObject).Value);
Related
I'm trying to retrieve the value for a particular property of an entity into a variable using the following code.
var item = db.Notices
.Where(a => a.ID == 0)
.Select(x => x
.GetType()
.GetProperty("Spell_ID")
.GetValue(x));
I'm just playing around with this at the moment, but at some point I'd like to be able to replace the 'Spell_ID' text with any column name and get the value dynamically. Not sure if I'm going the right way around this, but I'm getting the following error:-
LINQ to Entities does not recognize the method 'System.Object GetValue(System.Object)' method, and this method cannot be translated into a store expression.
I know I'm not doing this the right way (and I'm relatively new to C# MVC / LINQ), but I've spent so much time tinkering with the code I've lost my way...can somebody point me in the right direction please?
Your current code uses reflection to get the value of a property, but, from what I can infer from your exception message, db is an Entity Framework DbContext.
Entity framework does not support reflection at all, because your LINQ query is then converted into a SQL query by the framework itself. For this reason you have to change your approach if you really need to get a single property:
var items = db.Notices.Where(a => a.ID == 0).ToList();
var itemsProperty = items.Select(x => x.GetType().GetProperty("Spell_ID"));
This will fetch all the resources from the database and then execute the Select part in memory.
If you expect only a single entity from your database than this is a better approach:
var entity = db.Notices.SingleOrDefault(a => a.ID == 0);
var property = entity.GetType().GetProperty("Spell_ID");
Not to be tounge-in-cheek, but the error
LINQ to Entities does not recognize the method 'System.Object GetValue(System.Object)' method, and this method cannot be translated into a store expression.
is exactly what it sounds like. LINQ is unable to translate the GetValue() method to whatever it is that Entity Framework does exactly.
While there are ways to get EF and LINQ to recognize methods, its kinda a pain. The quickest solution would be to just use a loop.
I'm building an asp.net mvc app using Entity Framework, and I'm trying to order by a list. By a dynamic changed name, according to the name exists in the database.
bids = bids.OrderBy(s => s.PublisherName);
and the object:
public string PublisherName { get { db.Publishers.Find(pubid).Name; } }
But I'm getting an exception:
The specified type member 'PublisherName' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
What can I do? And how I can make it work?
Thanks.
Only initializers, entity members, and entity navigation properties
are supported.
db.Publishers.Find(pubid).Name; is neither initializer nor entity member, nor navigation property.
One possible way is to bring it on memory with AsEnumerable() :
bids = bids.AsEnumerable().OrderBy(s => s.PublisherName);
This will work perfectly as long as bids is small list of objects.
I believe Bidand Publisher are related, right? Maybe this will help you
var bids = from t in context.Bids
let u = t.Publishers.FirstOrDefault(i => i.Id == pubid)
orderby u.Name
select t;
Untested code, not sure if it will work for you!
When using Entity Framework via LINQ, all of the properties in the linq statement are translated in to SQL. EF only natively understands simple properties. It doesn't understand how to translate properties that contain actual code logic, which is what is causing the error you are seeing. The simplest way to fix this is to do the sort client side, outside of entity framework. The usual way to do this is to call .ToList on the unsorted result, and then sort the resulting list, which will happen client side.
I want to dynamically query an object with System.Linq.Dynamic.
var selectData = (from i in data
select i).AsQueryable().Where("Name = #0","Bob1");//This works fine with a non-entity object
I know that we cannot project onto a mapped entity. I believe that is the reason this code fails
foreach (var item in rawQuery.ObsDataResultList)
{
var propertyData = (from i in item
select i).AsQueryable().Where("PropertyName = #0", "blah");
}//item is a Entity Complex Type
Error
Could not find an implementation of the query pattern for
source type 'ClassLibrary1.Model.bhcs_ObsData_2_Result'. 'Select' not
found.
Given the fact that I need to specify the PropertyName at runtime, I don't see any way to project with an anonymous type or a DTO.
I don't need to retain any of the Entity functionality at this point, I just need the data. Copying the data onto something that is queryable is a valid solution. So, is it possible to query entity framework with dynamic LINQ?
And here is the entity class header (the thing I'm trying to query, aka the item object)
[EdmComplexTypeAttribute(NamespaceName="MyDbModel", Name="blah_myQuery_2_Result")]
[DataContractAttribute(IsReference=true)]
[Serializable()]
public partial class blah_myQuery_2_Result : ComplexObject
{
First of all, let me clarify that System.Linq.Dynamic is not a full fledged Microsoft product. It is just a sample we release some time ago, and we don't thoroughly test different LINQ implementations to work correctly with it. If you are looking for a fully supported text-based query language for EF ObjectContext API you should take a look at Entity SQL instead.
Besides that, if you want to use System.Linq.Dynamic and you are ok with testing yourself that you don't hit anything that will block your application from working, then I'll try to see if I can help. I am going to need additional information since I am not sure I understand everything in your code snippets.
First of all I would like to understand, in your first example what is "data" and where did it come from? In your second snippet, what is "rawQuery" and where did it come from? Besdies, what is rawQuery.DataResultList and what is rawQuery.ObsDataResultList?
Also regarding your second snippet, it seems that you are trying to compose with query operators on top of an object that is not actually of a query type (although that doesn't explain the error you are getting given that you are calling AsQueryable the compiler should have complained before that bhcs_ObsData_2_Result is not an IEnumerable nor a non-generic IEnumerable).
In your propposed answer you are saying that you tried with ObjectResult and that seemed to help. Just be aware that ObjectResult is not a query object and therefore it won't allow you to build queries that get send to the server. In other words, any query operators that you apply to ObjectResult will be evaluated in memory and if you don't keep this in mind you may end up bringing all the data from that table into memory before you apply any filtering.
Query ObjectResult<blah_myQuery_2_Result> directly instead of the item blah_myQuery_2_Result. For example
var result = (from i in rawQuery.DataResultList
select i).AsQueryable().Where("CreatedDTM > #0", DateTime.Now.Subtract(new TimeSpan(30, 0, 0, 0)));
I'm trying to implement a text search for database tables. I've a generic repository and don't really want to have to create derived ones for every model I might want to expose because there are quite a few in the database.
So the code I'm having difficulty with is as follows:
var props = typeof(T).GetProperties()
.Where(p => p.PropertyType == typeof(string));
IEnumerable<T> searched = null;
if (!string.IsNullOrWhiteSpace(searchTerm))
searched = sorted.Where(c => props
.Select(p => (string)p.GetValue(c, null))
.Select(v => v.Contains(searchTerm))
.Contains(true));
I'm feeding this a collection of PropertyInfo's obtained through a little reflection. Possibly not a high performance idea but I've yet to think of a better way. So these might be all properties of type string (searching all strings in the table) or it might be pulling certain properties in the model that have a custom Searchable attribute.
The runtime exception I'm getting is:
NotSupportedException: Unable to create a constant value of type 'System.Reflection.PropertyInfo'. Only primitive types ('such as
Int32, String, and Guid') are supported in this context.
I can see that I'm using reflection but not quite sure what exactly is causing the exception here. If someone could point this out then that would be much appreciated but if someone could suggest a better way to do this then that would be amazing. Thanks in advance!
The problem is that when the LINQ query is executed, it's trying to construct a SQL query to perform on the database. The exception message indicates that only primitive types can be used in the LINQ query because those are the only types that can be converted successfully into a SQL query.
Hopefully solving your problem, you just need to ensure that the database SQL query executes before extending the LINQ query using non-primitive types.
I'm guessing the sorted variable in your code snippet is a LINQ query, so call sorted.AsEnumerable() to execute the SQL query on the database and then you can perform the search functionality.
searched = sorted.AsEnumerable()
.Where(c => props.Select(p => (string)p.GetValue(c, null))
.Any(v => v.Contains(searchTerm)));
I'm hoping someone out in the SO community will be able to help me out here.
Simplified Background:
I'm using Entity Framework V1 to build my class structure that is outlined below, I'm using Table Per Type to persist my inherited objects:
Employee
CaseA : Case
CaseB : Case
CaseC : Case
CaseB has a Navigational Property to Employee
I have a Repository that returns an ObjectQuery. If the type of Case is actually CaseB, I need to include the Employee object within the graph. I can't .Include("Employee") because it's not a navigational property of Case, and Employee doesn't have a .Load() method on it.
Ideally I want to be able to do this in one query, however as a fall back I'm happy that I make a call, check the Object and perform another call, something like this: (although as I stated earlier, load doesn't exist on the employee navigational property)
//Get the case from the
Case myCase = new Repo<Case, Entities>.FirstOrDefault();
if(myCase is CaseB)
((CaseB)myCase).Employees.load();
Am I missing something really simple here?
Try this:
var employee = ctx.Cases
.OfType<CaseB>()
.Include("Employees")
.Select(x => x.Employees)
.FirstOrDefault();
OfType<T>() is one of the most important methods in EF when it comes to inheritance - you should familiarize yourself with it.
Essentially is filters the items in the query to be of a particular type - very similar to the conditional check your doing in your answer.
It's an IQueryable method (LINQ-Objects), but in LINQ-Entities (ObjectQuery<T>), it get's implemented as an INNER JOIN.
The above should work - just make sure you do the eager load after you do the OfType.
HTH.
As always, after posting the question I found this and this which has pointed me towards using projection (solution below), but I was hoping to avoid that, so I'm going to leave the question open to see if there is a more elegant solution.
var Employee = caseObjectQuery.Select(x => new{
Employee = x is CaseB ? (x as CaseB).Employee : null
}
).FirstOrDefault();
Just by selecting the Object into memory, EF magically maps the related entities.