I am having problems understanding lazy loading in Entity Framework 5. I understand when using lazy loading related entities are not loaded until requested:
"When using Lazy Loading, your initial query only brings in the target
entity set. But whenever you access a navigation property, another
query is issued against the store to load the related entity.
(reference)"
I have a ASP.NET Web API project with two classes:
public class Farm
{
public int FarmId { get; set; }
public virtual ICollection<LandUnit> LandUnits { get; set; }
...
}
public class LandUnit
{
public int LandUnitId { get; set; }
...
}
I set LazyLoadingEnabled = true, and have my POCO classes conforming to the guidelines (reference), but when I use scaffolding to create a FarmController and call it through fiddler, it shows:
JSON
{}
...
LandUnits
{}
...
If I set LazyLoadingEnabled = false, then I get:
JSON
{}
...
LandUnits=(null)
Am I misunderstanding the basics of lazy loading? It appears to me that what is occurring is the opposite of what the definition states. When lazy loading is off, related entities are not loaded. When lazy loading is on, related entities are loaded.
This is expected behaviour. When the JSON serializer comes to serialize the type, it will enumerate the LandUnits navigation property which will of course invoke the lazy load of that collection from the database.
When you switch lazy loading off, your navigation property will still be set to its default value as demonstrated, as no proxy type will be generated by Entity Framework.
I would recommend keeping lazy loading switched off, and eagerly (using the Include method) or explicly loading (using the Load method) the related data to ensure you aren't inadvertantly loading data that you don't require.
You should also be aware of circular dependency problems when using the default JSON serializer.
This just shows that you havent yet requested any of the LandUnits yet (if you loop through them using something like a foreach they will be loaded). So the JSON object is empty when using lazy loading.
When lazy loading is turned off, the LandUnits object is null as the LandUnits have not been loaded and cannot be loaded at a later time (attempting to do so would throw an error)
Related
Can anyone post correct and useful an example of using EF lazy loading in MVC application?
I've tried to research the question, but I can't get proper case.
As a result my conclusion is: since web apps are stateless there is no sense to include LL to entities. But it sounds strange. That's why the question is here.
Can you confirm or otherwise refute my conclusion?
EDIT
The statment "stateless" in question context is important in my mind. Let's pretend 2 scenarios. First one relates for example to WPF app and the second one to MVC. Let's suppose that thre is the next simple object:
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
...
public virtual List<Activity> Activities { get; set; }
}
1) WPF. User is able to request the only Person without his Activities. Thus he get a small portion of data. Overhead are reasonable. At the same time user can decide to request person's activities.
Due to ll mechanism, EF simply loads activities without requesting person object again, since Person still exists in application (of course, if we code it in such a way).
2) MVC. The same actions are there. But the only difference that, after server response, all resources including object Person are disposes. And we can't load Person activities as we did in WPF application. We are forced to load Person again (overhead is increases comparing with WPF app)
The point is that Lazy loading can be executed only in the scope of the context to which the entity is attached - if you dispose the context you cannot use it.
I don't think you understand what lazy loading does, as it has nothing to do with whether there's any state or not. It's not like caching or something. Lazy loading is simply Entity Framework overloading a property to add a custom getter that issues a query to fetch the object or set of objects when the property is accessed for the first time.
For example, if you had something like:
public class Foo
{
public virtual Bar Bar { get; set; }
}
And you were to query a set of Foos from the database, the Bar property on all of them would be null, as EF would not have issued any queries yet to fetch the related Bar instance. However, if you were to iterate over this list of Foo and access some property on Bar (i.e. foo.Bar.Baz, then EF would issue a just-in-time query for the Bar instance, so that it could then return the Baz property on it.
I have the following two models:
public class ModelA {
public IList<ModelB> list { get; set; }
// rest properties
}
public class ModelB {
public ModelA navProp { get; set; }
// rest properties
}
When my application loads, I fetch all the data; that is, instances of ModelA include all the values of the collection navigation property list.
In other words, I don't apply the eager loading or loading on demand techniques to fetch the data for the navigation property.
The problem with that is that I get the following error:
A MergeStrategy of 'Disallowed' does not allow you to attach an entity when an entity with the same key is already attached:
Looking at the code, I noticed that the first instance of ModelA is attached twice. It seems that breeze tries to recursively attach the entities into the cache (starting from the navigation property).
I just wonder if I'm following the wrong path. I have the impression that breeze expects us to explicitly load the related entities.
A bug that caused this error message was fixed in breeze 1.5.2.
Loading related object in MVC can be pretty confusing.
There are lots of terms you need to be aware of and learn if you really want to know what you're doing when writing your entity model classes and controllers.
A couple of questions that I've had for a very long time are: How does the virtual keyword work and when should I use it? And how does the Include extension method work and when should I use it?
Here's what I'm talking about;
virtual keyword:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LazyLoading.Models
{
public class Brand
{
public int BrandId { get; set; }
public string Name { get; set; }
public int ManufacturerId { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
}
}
And the Include extension method:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using LazyLoading.Models;
namespace LazyLoading.Controllers
{
public class LazyLoadingStoreController : Controller
{
private UsersContext db = new UsersContext();
//
// GET: /LazyLoadingStore/
public ActionResult Index()
{
var brands = db.Brands.Include(b => b.Manufacturer);
return View(brands.ToList());
}
... Other action methods ...
Notice that the Index() action method is autogenerated by Visual Studio. Yes, Visual Studio automatically added the .Include(b => b.Manufacturer). That's pretty nice.
Note: It took me too long to write this answer to just discard it when two other appeared ...
Virtual keyword works together with two properties DbContext.Configuration:
ProxyCreationEnabled - allows EF crating dynamic proxy when the object is created by the EF
LazyLoadingEnabled - allows dynamic proxy to load related entities when the navigation property is used for the first time
Lazy loading is transparently implemented through dynamic proxy. Dynamic proxy is class derived from your entity which is created and compiled by EF at runtime. It overrides your virtual navigation properties and implements logic checking if related entities were already loaded or not. If not it triggers a loading on the context (issues a new query to the database). Lazy loading can be executed only in the scope of the context to which the entity is attached - if you dispose the context you cannot use it.
Dynamic proxy creation is controlled by the first mentioned property. Once the entity instance is created as proxied you cannot "remove" the proxy. Also if you create entity without proxy (for example by calling constructor yourselves) you cannot add it later (but you can use DbSet<T>.Create instead of constructor to get the proxied instance).
The second property can be changed during live time of your entity instances so you can avoid unnecessary queries to the database when working with your entities by changing it to false (it is sometimes very useful).
Include represents eager loading. Eager loading loads related entities together with the main entity and it is executed as part of the main entity's query (it adds SQL joins to the query and builds a big result sets).
Benefit of eager loading is to get all data upfront with one roundtrip to the database. Especially if you know that you will need all of them it can be a way to go. Disadvantage of eager loading are very big result sets if you use too many includes as well as some limitations (you cannot add ordering or filtering to loaded entities - it always loads all related objects).
Benefit of lazy loading is to load data only when you really need them. It is helpful if you don't know upfront if you will really need them. Disadvantages are additional queries generated by EF in some scenarios when you don't expect them (any first access to the property will trigger the lazy loading - even Count on navigation collection will trigger loading of all data to be able to do count in your application instead of querying count from the database - this is called extra lazy loading and it is not natively supported by EF yet). Another big issue is N+1 problem. If you load several brands and you will access their manufacturer property by looping through all loaded brands without using eager loading, you will generate N+1 queries to database (where N is number of brands) - one for loading all brands and one for a manufacturer of each brand.
There is another option called explicit loading. It is like lazy loading but it is not transparently executed for you. You must execute it yourselves by using context class:
context.Entry(brand).Reference(b => b.Manufacturer).Load();
It is not very useful in this case but it would be useful if you have Brands navigation property on the Manufacturer class because you can do this:
var dataQuery = context.Entry(manufacturer).Collection(m => m.Brands).Query();
Now you have a IQueryable<Brand> instance and you can add any condition, ordering or even additional eager loading and execute it against the database.
I created a test MVC4 internet application.
Here's what I found:
First, create your entity model classes - notice the virtual keyword for the Manufacturer property:
public class Manufacturer
{
public int ManufacturerId { get; set; }
public string Name { get; set; }
public ICollection<Brand> Brands { get; set; }
}
public class Brand
{
public int BrandId { get; set; }
public string Name { get; set; }
public int ManufacturerId { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
}
Next, create your controller - I created (autogenerated using create new controller dialog) mine with CRUD action methods and views. Notice the Include extension method that was autogenerated automatically by Visual Studio thanks to the relationship in you Brand model class.
public class LazyLoadingStoreController : Controller
{
private UsersContext db = new UsersContext();
//
// GET: /LazyLoadingStore/
public ActionResult Index()
{
var brands = db.Brands.Include(b => b.Manufacturer);
return View(brands.ToList());
}
Let's remove the Include part for now so that our action method looks like this:
public ActionResult Index()
{
var brands = db.Brands;
return View(brands.ToList());
}
And this is how the Index view will look in Page Inspector after adding a couple of Brand objects - notice that Visual Studio automatically added the dropdown for Manufacturer and how it automatically scaffolded the Name column for Manufacturer - sweet!:
The Create action method:
//
// GET: /LazyLoadingStore/Create
public ActionResult Create()
{
ViewBag.ManufacturerId = new SelectList(db.Manufacturers, "ManufacturerId", "Name");
return View();
}
Awesome. Everything was autogenerated for us!
Now, what happens if we remove the virtual keyword from our Manufacturer property?
public class Brand
{
public int BrandId { get; set; }
public string Name { get; set; }
public int ManufacturerId { get; set; }
public Manufacturer Manufacturer { get; set; }
}
This is what will happen - our Manufacturer data is gone:
Okay, makes sense. What if I add back the Include extension method (with virtual still removed from the Manufacturer property)?
public ActionResult Index()
{
var brands = db.Brands.Include(b => b.Manufacturer);
return View(brands.ToList());
}
This is the result from adding back the Include extension method - The Manufacturer data is back!:
So that's how all that stuff work.
Next thing would be to explain what kind of T-SQL that gets generated behind the scenes in both cases (Lazy loading and Eager loading). That I'll leave to someone else. :)
Note: Visual Studio automatically generates Include(b => b.Manufacturer) wheather you add the virtual keyword or not.
Note2: Oh, yeah. Almost forgot. Here are some links to some good Microsoft resources.
http://msdn.microsoft.com/en-us/data/jj574232.aspx
http://msdn.microsoft.com/en-us/library/vstudio/bb896272(v=vs.100).aspx
The second link talks about performance considerations which the other link lacks if that is something that gets you going.
Lazy loading
Brand is a POCO (plain old CLR object). It is persistence ignorant. In other words: it does not know it is created by an Entity Framework data layer. It knows even less how to load its Manufacturer.
Still, when you do this
var brand = db.Brands.Find(1);
var manufacturer = brand.Manufacturer;
the Manufacturer is loaded on the fly ("lazily"). If you monitor the SQL that's sent to the database you'll see that a second query is emitted to fetch the Manufacturer.
That is because under the hood, EF does not create a Brand instance, but a derived type, a proxy, that's stuffed with wiring to execute lazy loading. That's why the virtual modifier is required for lazy loading to be enabled: the proxy must be able to override it.
Lazy loading is typically used in smart client applications where a context has a relatively long life span (e.g. context per form). Although I must say that even in smart client applications using short-lived contexts is beneficial and perfectly possible.
Eager loading
Eager loading means that you load an object with adhering objects (parents and/or children) in one take. That's what the Include method is for. In the example
db.Brands.Include(b => b.Manufacturer)
you'll see that EF creates a SQL query with a join and that accessing a Brand's Manufacturer does not spawn a separate query any more.
Eager loading is the way to go in most situations (esp. in disconnected scenarios), because the recommended way to deal with context instances is to use them and dispose them for each unit of work. Thus, lazy loading is not an option, because for a navigation property to be lazy loaded the context must be alive.
I am kind of confused about how Lazy loading working.
For example if I have supplier object, which have Address foreign object as a property, like this:
public class Supplier
{
public int ID { get; set; }
[Required]
public string FullName { get; set; }
public string TaxNumber { get; set; }
public virtual Address DeliveryAddress { get; set; }
}
when I put a break point at:
var suppliers = dbContext.Supplier.ToList();
I can see that Address information are available to the var suppliers, etc. when I expend the DeliveryAddress property, it is avaliable, is that means all the FK object has been loaded? But on the other hand, for the query on the right hand I can view that from Visual Studio at the break point, and it is like that:
{SELECT
[Extent1].[ID] AS [ID],
[Extent1].[FullName] AS [FullName],
[Extent1].[TaxNumber] AS [TaxNumber],
[Extent1].[DeliveryAddress_ID] AS [DeliveryAddress_ID]
FROM [dbo].[Suppliers] AS [Extent1]}
Which means the query itself wouldn't tying to load the Address object at all?
So who is loading the FK objects? ToList() or VS debugger?
Other suggestion about how to confirm that whether it is Lazy loading or not?
Note: So now I confirmed that Lazy loading is working by two ToList call, one set Lazy loading off, and another set lazy loading on. Could someone point me to a way to know at what point when lazy loading another query was sent for FK property?
The VS debugger loads the related object and it happens with a second SQL query, not the one you have shown in your question. When you drill into the address object in the debugger, the debugger accesses properties of the object to display their values. Accessing this object triggers lazy loading and the second SQL query.
Edit
This works because the parent object is not your Supplier type but a class which is derived from Supplier (a "proxy"). This derived class is created dynamically at runtime and has some cryptic autogenerated name (you should see this class name in the debugger). This dynamic class has the same properties as your base Supplier but it has overloaded the DeliveryAddress property. (That's the reason why those navigation properties must be virtual, otherwise overloading wouldn't be possible.) The query uses the FK column value which has already been fetched with your supplier query and retrieves the address by this value.
The new getter of the overloaded DeliveryAddress property which is called when you or the debugger accesses the property with supplier.DeliveryAddress contains at runtime generated code which runs a SQL query to load the related object from the database. The derived proxy class holds various additional internal members, especially a reference to the context/database connection (to be able to run a query at all) and a flag which indicates for the proxy object that it already has loaded the navigation property, so that it doesn't run a second redundant query when you access the DeliveryAddress a second time.
That's in short the way how lazy loading with POCOs works.
Imagine you have an entity that has some relations with other entities and you want to load only some of these entities to display them in diferent views.
For example, given this entity:
public class Category
{
public int id;
public Category child;
public Category parent;
}
In the view "ShowChild" you don't want to load the "parent" property since you are not showing it.
So, given this scenario I implemented a very nice "system" in my repository to load entities from DB filling only the properties I want. It works this way:
Category category = repo.FindCategory(id, (int)(LoadLevel.basic | LoadLevel.Child))
So now I have a category instance with only the id and Child properties loaded.
The dilemma I'm facing here is that if I define the LoadLevel in my serviceLayer (where it should be) I'll have to write two methods, "LoadCategoryWithChild" and "LoadCategoryWithParent" in my service class, one for each view (DRY violation?).
public class CategoryService
{
public Category LoadCategoryWithChild(int id)
{
int loadlevel = (int) (LoadLevel.Basic | LoadLevel.Child);
return repo.FindCategory(id, loadlevel);
}
}
OR, the other option I see is to define the loadlevel in the controller (MVC violation?) and implement just one method in my service class:
public class CategoryService
{
public Category LoadCategory(int id, int loadlevel)
{
return repo.FindCategory(id, loadlevel);
}
}
Which option would be better? I think that the DRY violation is much worse since it implies writing a lot of redundant code.
I definitely prefer the second solution by a long shot. I don't think it is a problem for the controller to give the service class a hint at what data it needs (which, frankly, is the same thing it is doing in the first solution by calling function A instead of function B).
I would change the second parameter to not be an int though and be an enum type so that the caller knows what the valid options are
This is probably the number one problem with Object Relational Mapping. Most ORM solutions get around it by having lazily loaded object properties, such that you only need one loading mechanism which caters to the majority of use cases. The minority function which uses additional properties can lazily load transparently what it needs from the View when its asked for via a proxy.
Personally I am not a fan of either of the solutions above or indeed the third solution of a transparent proxy. The proxy solution however will work more consistently, fail less frequently on minor changes in the View layer and the main impact is normally just a little performance. You can always optimise it when it proves to be a problem.
Hibernate as an example uses this approach, although you have to tell it whether a property is lazy loaded or not. Lazy loading via proxy in Hibernate also can't lazy load in all circumstances as it needs to be within a transaction. These limitations are there for a practical performance reasons. Of the database mapping approaches proxies/lazy loading is the easiest to use but it comes with its own complexities.
I suggest:
public Category LoadCategory(int id, params LoadLevel[] levels)
{
int loadLevel = LoadLevel.Basic;
foreach (var level in levels)
loadLevel = loadLevel | level;
return repo.FindCategory(id, loadlevel);
}
Example usage:
LoadCategory(0, LoadLevel.Parent, LoadLevel.Child); // self + parent+ child
LoadCategory(1, LoadLevel.Child); // self + child
LoadCategory(2); // self only