POCO entities and IsLoaded() in EF 4.1 - entity-framework-4

I'm working on an enterprise application that leverages the repository pattern on top of EF 4.1 with eager loading to POCO entities. Typically, a call will look like this:
public IEnumerable<SomeEntity> List(DateTime date)
{
using (var context = ContextFactory.CreateContext()) // Returns a DbContext
{
return CreateQuery<SomeEntity>(context)
.Include("PATH1")
.Include("PATH2")
.Where(...)
.AsNoTracking()
.ToList();
}
}
At some point, the business layer translates these entities into DTOs that are then transmitted via WCF to a web application.
As eager loading is rather expensive, I'm trying to keep .Include's to a minimum, so sometimes related properties are (eagerly) loaded and sometimes they're not. However, the business layer has no idea when related properties are present in the entity, so I get an ObjectContextDisposedException, the reason for which is perfectly clear to me and I don't intend to change the basic strategy (i.e. dispose the context right after eager loading the entities).
However, I need to check whether a particular related property is loaded or not, checking if the related object is null doesn't work (ObjectContextDisposedException), nor is there any kind of IsLoaded() method I could use.
Am I stuck with a try/catch block here or are there any other options?

Turn off lazy loading and check for null will work. Your current solution cannot use lazy loading because you dispose context immediately after running the query:
context.Configuration.LazyLoadingEnabled = false;

Related

How can I access lookup data via an injected service from within an entity?

My application is using DDD with .NET Core and EF Core. I have some business rules that run within an entity that need to check dates against a cached list of company holiday dates. The company holidays are loaded from the db and cached by an application service that is configured with our DI container so it can be injected into our controllers, etc.
I cannot determine how, or if it's the right/best approach, to get the service injected into the entity so it can grab those dates when running business rules. I did find this answer that appears to demonstrate one way to do it, but I wanted to see if there were any additional options because that way has a bit of a code-smell to me upon first glance (adding a property to the DbContext to grab off the private constructor injected context).
Are there any other ways to accomplish something like this?
ORM classes are very rarely your domain objects. If you can start with your domain and seamlessly map to an ORM without the need for infrastructure specific alterations or attributes then that is fine; else you need to split your domain objects from your ORM objects.
You should not inject any services or repositories into aggregates. Aggregates should focus on the command/transactional side of the solution and work with pre-loaded state and should avoid requesting additional state through any handed mechanisms. The state should be obtained and handed to the aggregate.
In your specific scenario I would suggest loading your BusinessCalendar and then hand it to your aggregate when performing some function, e.g.:
public class TheAggregate
{
public bool AttemptRegistration(BusinessCalendar calendar)
{
if (!calendar.IsWorkingDay(DateTime.Now))
{
return false;
}
// ... registration code
return true;
}
// or perhaps...
public void Register(DateTime registrationDate, BusinessCalendar calendar)
{
if (!calendar.IsWorkingDay(registrationDate))
{
throw new InvalidOperationException();
}
// ... registration code
}
}
Another take on this is to have your domain ignore this bit and place the burden on the calling code. In this way if you ask you domain to do something it will do so since, perhaps, a registration on a non-working day (in my trivial example) may be performed in some circumstances. In these cases the application layer is responsible for checking the calendar for "normal" registration or overriding the default behaviour in some circumstances. This is the same approach one would take for authorisation. The application layer is responsible for authorisation and the domain should not care about that. If you can call the domain code then you have been authorised to do so.

Proper implementation of Repository Pattern using IQueryables?

I'm building a Repository layer for my MVC application with methods like GetObject, UpdateObject, DeleteObject, etc.
This is what I have now:
public List<Object> GetObjects()
{
return _db.Objects.Where(o => o.IsArchived == false).ToList();
}
But I'm wondering if it would be better to return IQueryables for lists so that the least amount of data gets sent to the client when filters are applied in the UoW or Service layers. Would it be best to do something like this?
public IQueryable<Object> GetObjects()
{
return _db.Objects.Where(o => o.IsArchived == false);
}
The not nice thing about returning IQueryable, is that if you ever have a different implementation of repository, say using different ORM, storing data in non-SQL database, cloud or XML file, it would be hard to implement same interface. It would be much easier to implement if you return more generic colections of domain objects. For example IEnumerable. You can always pass filtering criteria in.
The other drawback of returning IQueryable, is that it may happen, that when you actually run the query your object context may be already disposed (Depending on your implementation) or may be kept in memory longer than required.
A leaky abstraction such as IQueryable could cause problems, for example imagine you want to get some data from database and order it by Guid. If you enumerate the query by calling ToList() prior to sorting, you'll get different results if you do it after. The reason is that in first case the sorting will happen in .NET, but in other case it will happen in SQL which uses completely different order.
The nice thing about returning IQueryable here is that you can continue to build up your query further without hitting the db. Once you call ToList it will hit the db and you can't customize your query further without hitting the database a second time.

How to prevent lazy loading of entities that were already manually loaded when navigating a property in EntityFramework

Background:
I am using EF4 and ObjectContext. To optimze retrieval of complex object hierarchies, I manually execute database queries and then use ObjectContext.Translatey<T>(DataReader, entitySetName, mergeOptions.AppendOnly) to turn data rows into entities. I then attach the entities to the ObjectContext with Attach method. This also fixes relations between entities.
The problem:
After everything is loaded and set up I try to navigate from parent entity to a child entity (for example Parent.Childs.First()), but EF hits the database to load the kids, even though all the child entities are already present in the ObjectContext and EntitySet. It looks like the reason for this is that parent.Childs.IsLoaded is set to false which makes EF think that it still needs to load the relation.
Question:
How can I tell EF that EntitySet has already been loaded?
Is there a supported way to set RelatedEnd.IsLoaded to true. I wouldn't like to mess with the calling the RelatedEnd.SetIsLoaded internal method.
I found a smilar question here but it relates to DbContext and has no satifying answer ;-)
Matra
It looks like this was implemented in this change:
http://entityframework.codeplex.com/workitem/269
You can now iterate through your entities and tell them that their child collections are already loaded:
foreach (var entity in loadedEntities)
context.Entry(entity).Collection(a => a.SomeChildCollection).IsLoaded = true;
This will prevent entities in SomeChildCollection from being loaded when they are accessed from entity.
I'm not exactly sure what version of EF this appeared in but I'm guessing 6.0.0.
The only way to solve this is to turn off lazy loading. The question you have found on MSDN asks about DbContext but the answer mentions that there is no way to change the value in underlying libraries - ObjectContext API (= EF4 in your case) is the underlying library. Even in .NET 4.5 (EF5) setting IsLoaded is still not available on public API.

MVC and Entity Framework when to Dispose Entity objects

When do you dispose an Entities object context objects in entity framework and MVC?
For example if I have a persons table and I select a record in a controller method, dispose it and pass it back to my view, then the record won't be usable in the view.
Should I be disposing it somehow after my view is processed? or not disposing it at all?
One option is to create it in Global.asax's begin request event, and dispose of it in Global.asax's end request event. Every page simply uses that one (stored and obtained in HttpContext.Current.Items or in thread local storage) without disposing it. That lets it be available to your view to do lazy loading but still disposes of it after the request is completed.
The other option is to make sure everything you need is already loaded before calling your view (via .First(), .ToList(), and .Include(property) to include navigation property data) and dispose of it immediately. Both methods work.
I assume you're talking about disposing the Entity Framework "Contexts," since the objects themselves aren't disposable.
We've found it best to leave the entities themselves in our data layer and map them to POCOs/DTOs that contain all the information we need for a given view. That way we're not trying to lazy-load data while we render our view. We wrap the data-access code in a using(var context = contextFactory.Get()), so that the context will automatically be disposed before the method ends, but after we have loaded all the data we're retrieving into an in-memory collection.
Let's consider typical usage pattern of user, you will never just open one item and go away, in fact we move back and forth between items, search and review items again, modify and save them.
If you keep your ObjectContext alive for entire session, you will use little more memory per user, but you will reduce your application to database transfers, and you will be able to accumulate changes. And save changes at once. Since EF implements Identity Pattern, you will not be loading multiple copies of same object.
Otherwise if you dispose ObjectContext, will reduce memory but will increase overhead of loading objects again and again. You might be loading multiple copies of same object again and again over views and increasing query load on database server.

MVC Repository Pattern: Creating Model Classes

Reviewing Conery's storefront, and I dont understand why he used Linqs auto-generated classes (ie Order class) and then he has another Order class defined that is not a partial class. WHen using repository pattern should one manually create the classes, and disregard Datacontext altogether?
If you don't decouple your front end from the linq classes using an intermediary class, you can't control with the data context gets garbage collected. Typically with data context types of instances you want to rid of them as soon as you're done using them. Here's how you might want to do this with the linq to sql context:
using (MyDataContext data = new MyDataContext())
{
SomeThing thing = data.Things(t => t.ID == 1);
return thing;
}
... the MyDataContext instance is gone
With the "using" block, you're disposing of the instance of MYDataContext at the last "}". However, if you do this you'll get an error then trying to use "thing" because the data context instance is gone. If you don't dispose of the data context, it's left hanging around until it's eventually garbage collected.
If you introduce an intermediary class to decouple the linq to sql code from the calling app you can still get rid of your data context instance and return the same data (just in a different object):
using (MyDataContext data = new MyDataContext())
{
SomeThing thing = data.Things(t => t.ID == 1);
SometThingElse otherThing = ConvertSomethingToSomethingElse(thing);
return otherThing;
}
... the MyDataContext instance is gone
Hope that helps.
Rob has answered on this question in one of his show.
He Using POCO classes to be aware from all dataaccess classes. For example when he change LINQ-to-SQL to NHibernate all he will need to do i change his "mappings" in his filters, and he will not have to make any changes in bussiness logic.
He said in one of his recent videos he doesn't like the way LINQ to SQL does mapping. I agree though I think it is complete overkill.
I'd say you're not breaking any major design patterns as long as you're sticking to the repository pattern itself. I think it's a matter of choice to have 2 sets of classesa, allbeit a bad one, still a choice.

Resources