Extending an Entity Framework property - c#

I have an entity called File, I created a partial class with a property on it.
I was able to use this property in regular constructors and other statements. But this property is not accepted in any linq statement.
I am getting the following exception.
Exception
The specified type member 'FileStatus' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
Code
var fileEntry = from entry in context.ICFiles
where entry.FileName == FileName &&
entry.FileStatus == FileStatus.InProgress
select entry;
fileEntry.First().FileStatus = FileStatus.Completed;
// This is where I get the exception
Property Definition
public partial class ICFile
{
[DataMemberAttribute()]
public FileStatus FileStatus
{
get
{
return (FileStatus)this.Status;
}
set
{
this.Status = (int)value;
}
}
}

I think the problem is that the entity framework is trying to convert your FileStatus property to a column in the database, where it does not exist and there is no mapping information for it to go on as you have defined it in a partial class.
I see that you are trying to cast to an enumeration, because presumably you are using an Entity Framework version before the version 5 beta that apparently has enum support (I may be wrong on that, perhaps it is still missing).
Sadly enumerations do not really work very well in the current Entity Framework version (4.3.1). There are various kludges you can do but none are very satisfactory and you often end up with accidentally loading the entire table into memory or something equally horrendous (see Using ADO.net Entity Framework 4 with Enumerations? How do I do it?).
Personally I would just not bother with the partial class and do your query like this, to keep things simple:
var fileEntry = from entry in context.ICFiles
where entry.FileName == FileName &&
entry.Status == (int)FileStatus.InProgress
select entry;
fileEntry.First().Status = (int)FileStatus.Completed;
Not ideal, but it works and it shows what is happening and you know that the where clause will be correctly translated to an equivalent bit of SQL to run against the database (I think that is called "pragmatic").

I don't think the way you use Enums in your code example is causing any issues. The problem is simply that your class extension property is not recognized by EF as a member of ICFiles since it is not really in your edmx model nor a column in your database table. Use the code example user1039947 gave you and you should be fine.
You can however use your original query when doing a LINQ to Object search on an ICFiles IEnumerable instance. This is because LINQ to Entities is translated into SQL before fetching data from the database, while LINQ to objects is done in memory. Your FileStatus property does not exist in your database, only in memory.

Right when I asked the question, I was left with the answer that #user1039947 has posted. However, that's not the one I was expecting as an answer for this question.
I was looking for the ability of Entity framework to utilize the Enum completely. But eventually I figured out that Linq to Entity can't recognize the Enums (it usually recognizes the entities through an attribute starting with Edm, like EdmTypeAttribute, EntityPropertyAttribute etc.)
Linq to Entity of Framework 4.0, has no way to accept the enums as entity object. However, the partial method serves us 80% what we might need from enum.
I have posted a blog with more detail on this.

Related

Entity Framework: Searching in DB using a generic function?

I have quite some entities in the DB and all of them have a column decimal DBSTATE indicating if the entry is active (1) or not (0). To make a quick work of getting the instances, I created the following generic function that returns only the active columns of entities:
IEnumerable<DBType> GetActiveEntries<DBType>()
where DBType : class, IDBEntry
{
return db.Set<DBType>().Where(e => e.DBStateInDB == (decimal)DBState.Active).AsEnumerable();
}
IDBEntry is an interface that all the model classes implement by returning its DBSTATE value, e.g. this is how REGULARCUSTOMER implements it (irrelevant parts are omitted):
public decimal DBStateInDB => this.DBSTATE
As it turns out, this is not possible, because EF can only work with its own types in queries, this is why the following non-generic function works:
IEnumerable<REGULARCUSTOMER> GetActives_TEMP()
{
return db.REGULARCUSTOMERs.Where(e => e.DBSTATE == (decimal)DBState.Active).AsEnumerable();
}
So my question: is it possible to somehow avoid writing separate functions/switch-cases for all the entities or I really stuck with that option?
I'd say you have to go around the problem.
One possible way of doing it would be to add Navigational properties (by creating a new entity type) to your entities, as DbSet<EntityState> (for example) which your entity would have a ForeignKey defining the State, this would oblige you to have a supplementary table which would contain the ID's of every entity and a bool for their state, making it clean and accessible. This also means that with your newly created Navigational property you could access it with YOUR_ENTITY.EntityState.State or YOUR_ENTITY.EntityState.Id, it would also give you the capacity to modify/access a entities State regardless of their type because of the new table. Your type enherited rules will still apply and changing the table will change the entity, regardless of Type.
But again, this is only a way of doing. It should be relatively simple to implement and can be quite powerful.
Let me know what you think.

entity framework 4: where is my load method and IsLoaded property?

I am using EF4, and I using the System.Data.Entity dll in my class. However, I can't see the load method of my navigation property of my entity.
How can I access to this method?
What I am doing is create e 4.0 project of .NET, create my edmx from a database, right click in the model edmx and I generate a DBContext.
However, I can access to the local property of my context, that I think that is a feature of EF4.
Thanks.
Daimroc.
For the DbContext approach, the IsLoaded property and Load method have been moved:
context.Entry(yourEntity)
.Collection(entity => entity.NavigationProperty)
.IsLoaded;
context.Entry(yourEntity)
.Collection(entity => entity.NavigationProperty)
.Load();
Entry method: http://msdn.microsoft.com/en-us/library/gg696578(v=vs.103).aspx
Collection method: http://msdn.microsoft.com/en-us/library/gg671324(v=vs.103).aspx
IsLoaded property: http://msdn.microsoft.com/en-us/library/gg696146(v=vs.103).aspx
Load method: http://msdn.microsoft.com/en-us/library/gg696220(v=vs.103).aspx
When you write the query (all this also works with lambda syntax as well btw)
From a in context.EntitySet.Include("Navigation Property NAme")
select a
and all will be there ;) .. or more to the point the navigation properties will be populated.
can be wierd with lots of joins though
you can also
From a in context.EntitySet.Include("Navigation1.Navigation2.Navigation2")
.Include("SomeOtherNavigation")
select a
where navigation1 and SomeOtherNavigation are navigation properties on the entity set
Failing that you can turn on lazy loading in the context. But its evil imo.
Also it doesnt really scale well when you go for an SOA approach as you need to include prior to knowing about the lazy load in your repository.
Ie you run the query in your repository, send stuff over the service and then want the navigation properties in the front end ... by which time its too late to lazy load ... EG you are using a wcf service that doesn't use data services.
Important to note that you ahve to use Include on the EntitySet, it is not on an IQueryable<>.
A real example:
var csg = from ucsg in c.UserCarShareGroups.Include("UserCarShareGroups.User.UserVehicles")
where ucsg.User.UserName.ToLower() == userName.ToLower()
&& ucsg.CarShareGroup.Carpark.Name.ToLower().Equals(carparkName.ToLower())
&& ucsg.DeletedBy == null
select ucsg.CarShareGroup;
(the database has case sensitive collation for some reason)
An alternate approach (and maybe more relevant is here)
Entity Framework - Trouble with .Load()
However I like doing it the way I said because it is explicit and I know exactly what is being pulled out. Especially when dealing with large datasets.
An answer to a question that combines my concerns with Load() is here:
Entity Framework 4 load and include combine

Adding behavior to LINQ to Entities models

What's the preferred approach when using L2E to add behavior to the objects in the data model?
Having a wrapper class that implements the behavior you need with only the data you need
using (var dbh = new ffEntities())
{
var query = from feed in dbh.feeds select
new FFFeed(feed.name, new Uri(feed.uri), feed.refresh);
return query.ToList();
}
//Later in a separate place, not even in the same class
foreach (FFeed feed in feedList) { feed.doX(); }
Using directly the data model instances and have a method that operates over the IEnumerable of those instances
using (var dbh = new ffEntities())
{
var query = from feed in dbh.feeds select feed;
return query.ToList();
}
//Later in a separate place, not even in the same class
foreach (feeds feed in feedList) { doX(feed); }
Using extension methods on the data model class so it ends up having the extra methods the wrapper would have.
public static class dataModelExtensions {
public static void doX(this feeds source) {
//do X
}
}
//Later in a separate place, not even in the same class
foreach (feeds feed in feedList) { feed.doX(); }
Which one is best? I tend to favor the last approach as it's clean, doesn't interfere with the CRUD facilities (i can just use it to insert/update/delete directly, no need to wrap things back), but I wonder if there's a downside I haven't seen.
Is there a fourth approach? I fail at grasping LINQ's philosophy a bit, especially regarding LINQ to Entities.
The Entity classes are partial classes as far as i know, so you can add another file extending them directly using the partial keyword.
Else, i usually have a wrapper class, i.e. my ViewModel (i'm using WPF with MVVM). I also have some generic Helper classes with fluent interfaces that i use to add specific query filters to my ViewModel.
I think it's a mistake to put behaviors on entity types at all.
The Entity Framework is based around the Entity Data Model, described by one of its architects as "very close to the object data model of .NET, modulo the behaviors." Put another way, your entity model is designed to map relational data into object space, but it should not be extended with methods. Save your methods for business types.
Unlike some other ORMs, you are not stuck with whatever object type comes out of the black box. You can project to nearly any type with LINQ, even if it is shaped differently than your entity types. So use entity types for mapping only, not for business code, data transfer, or presentation models.
Entity types are declared partial when code is generated. This leads some developers to attempt to extend them into business types. This is a mistake. Indeed, it is rarely a good idea to extend entity types. The properties created within your entity model can be queried in LINQ to Entities; properties or methods you add to the partial class cannot be included in a query.
Consider these examples of a business method:
public Decimal CalculateEarnings(Guid id)
{
var timeRecord = (from tr in Context.TimeRecords
.Include(“Employee.Person”)
.Include(“Job.Steps”)
.Include(“TheWorld.And.ItsDog”)
where tr.Id = id
select tr).First();
// Calculate has deep knowledge of entity model
return EarningsHelpers.Calculate(timeRecord);
}
What's wrong with this method? The generated SQL is going to be ferociously complex, because we have asked the Entity Framework to materialize instances of entire objects merely to get at the minority of properties required by the Calculate method. The code is also fragile. Changing the model will not only break the eager loading (via the Include calls), but will also break the Calculate method.
The Single Responsibility Principle states that a class should have only one reason to change. In the example shown on the screen, the EarningsHelpers type has the responsibility both of actually calculating earnings and of keeping up-to-date with changes to the entity model. The first responsibility seems correct, the second doesn't sound right. Let's see if we can fix that.
public Decimal CalculateEarnings(Guid id)
{
var timeData = from tr in Context.TimeRecords
where tr.Id = id
select new EarningsCalculationContext
{
Salary = tr.Employee.Salary,
StepRates = from s in tr.Job.Steps
select s.Rate,
TotalHours = tr.Stop – tr.Start
}.First();
// Calculate has no knowledge of entity model
return EarningsHelpers.Calculate(timeData);
}
In the next example, I have rewritten the LINQ query to pick out only the bits of information required by the Calculate method, and project that information onto a type which rolls up the arguments for the Calculate method. If writing a new type just to pass arguments to a method seemed like too much work, I could have also projected onto an anonymous type, and passed Salary, StepRates, and TotalHours as individual arguments. But either way, we have fixed the dependency of EarningsHelpers on the entity model, and as a free bonus we've gotten more efficient SQL, as well.
You might look at this code and wonder what would happen if the Job property of TimeRecord where nullable. Wouldn't I get a null reference exception?
No, I would not. This code will not be compiled and executed as IL; it will be translated to SQL. LINQ to Entities coalesces null references. In the example query shown on the screen, StepRates would simply return null if Job was null. You can think of this as being identical to lazy loading, except without the extra database queries. The code says, "If there is a job, then load the rates from its steps."
An additional benefit of this kind of architecture is that it makes unit testing of the Web assembly very easy. Unit tests should not access a database, generally speaking (put another way, tests which do access a database are integration tests rather than unit tests). It's quite easy to write a mock repository which returns arrays of objects as Queryables rather than actually going to the Entity Framework.

Does Entity Framework/LINQ to SQL Data Binding use reflection?

Forgive me if this has been asked before; I did a search but couldn't find anything that specifically answered this question, but I'd be happy to be referred.
I'm taking a peek at both the Entity Framework and LINQ to SQL, and while I like the systems (and of course the LINQ integration) I'm a little skeptical on the data-binding aspect. I've taken query results and inspected them, and they don't appear to implement the standard .NET list-binding interfaces (IBindingList, and more importantly ITypedList), leading me to believe that binding them to a grid (or anything else) is going to use reflection to get/set my entity properties. This seems like a comparatively expensive operation, especially when all of the code is generated anyway and could implement the interfaces.
Does anyone have any insight into this? Is reflection used to get/set the value of the properties? If yes, does this have a performance impact that's noticeable, and does anyone have any idea why they went this route?
Edit
I'm actually concentrating on whether or not ITypedList is implemented somewhere along the way, as that's what has the capability to provide an explicit mechanism for defining and interacting with properties without resorting to reflection. While I didn't have a LINQ to SQL project up, I did inspect a simple Entity Framework entity query result, and it did not appear to implement ITypedList. Does anyone know if I'm just looking at something incorrectly, or if not why this is the case?
Edit 2
After accepting Marc's answer, I thought it might be helpful for others if I posted some simple code I used to seamlessly implement his solution. I put the following in the static constructor for my class:
public static ContextName()
{
foreach(Type type in System.Reflection.Assembly.GetExecutingAssembly()
.GetTypes())
{
if (type.GetCustomAttributes(typeof(System.Data.Linq.Mapping
.TableAttribute), true) != null)
{
System.ComponentModel.TypeDescriptor.AddProvider(
new Hyper.ComponentModel.HyperTypeDescriptionProvider(
System.ComponentModel.TypeDescriptor.GetProvider(
type)),
type);
}
}
}
While this is for LINQ to SQL, I'm sure an equivalent version could be written for the Entity Framework. This will scan the assembly for any types with the Table attribute and add a custom provider for each of them.
The Expression API that underpins LINQ etc is founded on reflection (MemberInfo), not the component-model (PropertyDescriptor etc) - so there is not a huge requirement for ITypedList. Instead, the contents are inferred from the T in IQueryable<T>, IEnumerable<T> and IList<T> etc.
The closest you might get is IListSource, but that will still just be a shallow wrapper around a proper typed list.
If performance of runtime binding (to PropertyDescriptor) is key, you might want to look at HyperDescriptor - which uses Reflection.Emit and TypeDescriptionProvider to wrap the component-model.
Re the "why" etc; note that in almost all cases with LINQ-to-SQL and EF the Expression (or the "create and set members" part) is going to be compiled to a delegate before it is invoked - so at runtime there is no huge reflection cost. And likewise, with LINQ-to-Objects everything is already compiled (by the C# compiler).
In my experience with LINQ to SQL, I have concluded for a few reasons that LINQ is using reflection to set and get field values in entity class instances. I don't know if I can remember all the reasons, but here's what I can tell you.
If I recall correctly, LINQ does not call any property procedures, but directly sets and reads all the private field values directly, which can only be done via reflection, as far as I know.
The names provided by the MetaData (in the attributes on the entity class properties) provide field name information in string form (if the database column and property name are different, for example). You can conclude from this that LINQ must be using reflection to look up the member to access it.
I think it does this to enforce simplicity -- you can rely on the values in the fields in the entity class directly mirroring the database column values, and there's not much overhead in retrieving the object from the database (populating a newly created entity to correspond to values retrieved from the database should not be routed through property procedures). One thing I have done to represent enumerated values retrieved from the database, for example, is to make some of the LINQ-generated properties private and wrap them in a manually coded property in a partial class that reads and writes the LINQ property.
From looking at what MSDN has to say on LINQ to SQL data binding, it does seem to use IListSource or IBindingList.
Btw, LINQ uses Expression Trees, and that is not reflection as much as meta-programming. Performance should be much better than reflection. Charlie Calvert covers this a bit in this article.

LinqToSQL - no supported translation to SQL

I have been puzzling over a problem this morning with LinqToSQL. I'll try and summarise with the abbreviated example below to explain my point.
I have DB two tables:
table Parent
{
ParentId
}
table Child
{
ChildId
ParentId [FK]
Name
Age
}
These have LinqToSQL equivalent classes in my project, however, I have written two custom model classes that I want my UI to use, instead of using the LinqToSQL classes.
My data access from the front end goes through a service class, which in turn calls a repository class, which queries the data via linq.
At the repository level I return an IQueryable by:
return from data in _data.Children
select new CustomModel.Child
{
ChildId = data.ChildId,
ParentId = date.ParentId
};
My service layer then adds an additional query restriction by parent before returning the list of children for that parent.
return _repository.GetAllChildren().Where(c => c.Parent.ParentId == parentId).ToList();
So at this point, I get the method has no supported translation to sql error when I run everything as the c.Parent property of my custom model cannot be converted. [The c.Parent property is an object reference to the linked parent model class.]
That all makes sense so my question is this:
Can you provide the querying process
with some rules that will convert a
predicate expression into the correct
piece of SQL to run at the database
and therefore not trigger an error?
I haven't done much work with linq up to now so forgive my lack of experience if I haven't explained this well enough.
Also, for those commenting on my choice of architecture, I have changed it to get around this problem and I am just playing around with ideas at this stage. I'd like to know if there is an answer for future reference.
Many thanks if anyone can help.
Firstly, it begs the question: why is the repository returning the UI types? If the repo returned the database types, this wouldn't be an issue. Consider refactoring so that the repo deals only with the data model, and the UI does the translation at the end (after any composition).
If you mean "and have it translate down to the database" - then basically, no. Composable queries can only use types defined in the LINQ-to-SQL model, and a handful of supported standard functions. Something similar came up recently on a related question, see here.
For some scenarios (unusual logic, but using the typed defined in the LINQ-to-SQL model), you can use UDFs at the database, and write the logic yourself (in TSQL) - but only with LINQ-to-SQL (not EF).
If the volume isn't high, you can use LINQ-to-Objects for the last bit. Just add an .AsEnumerable() before the affected Where - this will do this bit of logic back in managed .NET code (but the predicate won't be used in the database query):
return _repository.GetAllChildren().AsEnumerable()
.Where(c => c.Parent.ParentId == parentId).ToList();

Categories

Resources