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.
Related
I want to get a list of all actual column names in my EF entity. I explicitly don't want the navigation properties, though. I already found this question, which is pretty straight forward, but ignores the second requirement.
My first approach was, to filter the property types with a Linq where clause. I could check for IEnumerable or Lazy<T>. But I guess, that Lazy<T> doesn't implement IEnumerable and I haven't found a way to do a generic Lazy check. Is this even the best approach, or are there any better?
I believe I have found what I want in terms of a main class for operations in Entity, but do not know how exactly to wire it up to the database, and MSDN is precious short on documentation (Google is even less useful).
Again, pardon my ignorance, as I am new to this, and only recently coming up to speed, but how would I get this to connect or reflect this change with the database? I am just not seeing a path between this, and say DbContext. Do I craft a query by hand? Is there some special class I am missing that provides some functionality I've been missing over the last three days that I've been trying to coax this framework into doing just anything minimally useful? Thanks to anyone who accepts this arduous task.
EntityCollection<T> newCollection = new EntityCollection<T>();
newCollection.Add(objectValue);
I mean, is EntityCollection just a List / Array for Entities? Or does it have some back-end hooks to the database? Can it perform updates / deletes when its methods are called, and are these magical in nature, or is there some prep work that makes the magic work?
As I understand, this class behaves just like the List<T> class - i.e. it's an in-memory collection.
Look at this answer: ObjectSet.AddObject() vs. EntityCollection.Add()
But if you'll look at the MSDN documentation about its Add method so you'll see that it could be related to the ObjectContext and eventually to the data-source(Database):
The Add method adds an object to an EntityCollection and
creates a relationship between the two objects. When the source object
is attached to an ObjectContext instance, the Add method also adds the
object to the ObjectContext. This operation is translated into an
insert operation in the data source when SaveChanges is called. For
more information, see Adding, Modifying, and Deleting Objects (Entity
Framework).
I will start by saying I have already looked thoroughly in stack overflow, nhusers and the documentation for a possible solution to my issue.
I need to be able to query only the base class table in parts of my multi/future query when eagerly loading associations (although from the research I have done I don't think this is possible)
I have started to map an existing schema using fluent nhibernate as a proof of concept. I have mapped an inheritance hierarchy using table per sub class (The mappings all work perfectly fine so I won't paste them all in here). The hierarchy has around 15 sub classes and the base class has some additional associations. E.g.
Base
Dictionary<string, Attribute> Attributes
List<EntityChange> Changes
I need to eagerly load both of the collections as in the given scenario they are required for post processing and lazily loading them causes performance issues. I am eagerly loading them by a multi / future query:
var baseQuery = session.CreateCriteria<Base>("b")
.CreateCriteria("Nested", JoinType.LeftOuterJoin)
.CreateCriteria("Nested2", JoinType.LeftOuterJoin)
.CreateCriteria("Nested2.AdditionalNested", JoinType.LeftOuterJoin);
var logsQuery = session.CreateCriteria<Base>("b").CreateAlias("Changes", "c", JoinType.LeftOuterJoin,
Expression.And(Expression.Ge("c.EntryDate", changesStartDate), Expression.Le("c.EntryDate", changesEndDate)))
.AddOrder(Order.Desc("c.EntryDate"));
var attributesQuery = session.CreateCriteria<Base>("t").SetFetchMode("Attributes", FetchMode.Join);
logsQuery.Future<Base>();
attributesQuery.Future<Base>();
var results = baseQuery.Future<Base>().ToList();
The queries execute and return the correct results. But just to eagerly load the associations in this manner means that the attribute and changes queries have to perform a polymorphic fetch (the addition of about 15 left outer joins per query that aren't required). I know this is required for polymorphic querying but the base query will return the hierarchy that I desire. The other parts of the multi query that are issuing a polymorphic query are redundant.
I haven't yet mapped the whole of the hierarchy so there will be additional unecessary joins being performed and there are also other associations that could be loaded up front. These two combined without the addition of an increase in volume will lead to performance issues. The performance currently of this query is about 6 seconds (which admittedly is better than the 20 it's currently taking) but by messing around a bit with the query and taking out the extra joins I can get it down to about 2 seconds (this is a common query so getting it as low as possible is beneficial not just pleasing to me. It will also be run from multiple distributed machine so I would rather not get into a discussion about caching / 2nd level caching).
I have tried
using the class modifier in the query 'class = base'. I initially done this blindly but believe this is for discriminator values. Even if it is for the case statement in the SQL this will not prevent the extra joins.
Doing everything in a single query. This is slower than splitting it up as above and gives the cartesian product
Using 'Polymorphism.Explicit();' in the fluent mappings. This has no effect as I am using ClassMap with SubclassMaps so it is ignored. I tried changing all the maps to ClassMaps and using Join but this didn't give the desired behaviour.
Tried to trick nhibernate into joining the base class table onto itself for loading associations (basically load a more concrete type to prevent the polymorphic query) - create a derived class 'BaseOnlyLoading' which uses the same table and primary key as the base class. This was obviously a hack but I was just trying to see what's possible. NHibernate doesn't allow the class and sub class to use the same table.
Define the BaseOnlyLoadingMap to be a classmap with the same assocations as the BaseMap with a join back onto the Base. This was hopeful as assocation collections are resolved in the context based on full type name.
Use an interceptor which modifies the SQL that before it's execute. I wouldn't use this in production and just tried it out of interest. I passed an interceptor into a local session. This caused issues and I didn't proceed.
The HQL 'Type' query operator as explained here although I am not sure this has been implemented in the .NET version and might behave similarly to 1.
There is comment on highest rated answer (How to perform a non-polymorphic HQL query in Hibernate?) which suggest overriding the IsExplicitPolymorphism on the persister. I had a quick look and from what I remember the persister was either global per entity or created in the SessionImpl from a static factory which would prevent doing this. Even if this was possible I am not sure what sort of side effects this would have.
I tried using some SQL to load everything but even if I use a stored proc I am not sure how nhibernate will piece the graph back together. Maybe I could specify all the entities and aliases?
Specifying explicit per query would be nice. Any suggestions?
Thanks in advance.
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.
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();