views:

195

answers:

2

Suppose I have a couple of table:

person(personid, name, email)
employee(personid,cardno, departmentID)   //personid,departmentID is foreign key
department(departmentID, departmentName)
employeePhone(personID, phoneID)   //this is relationship table
phone(phoneID, phonenumer)

When EntityFramework generate entity class for employee, this class have members like:

public partial class employee{
  int _personid;
  string _cardno;
  string _departmentName;
  person _person;
  department _department;  
  //......
}

by default, when this class is loaded, only data available for employee table column, not data for associated entities data loaded. If I use Linq to get the data at client side, Include should be used for linq query.

My question is: I want to the associated entities data loaded at server side when the employee is instantiated at server side. So when I get the entity at client side, all data available already so that I can easy to bind it to UI.

How to implement this request?

A: 

What you are hoping for is Lazy loading of the dependent Entities. There is an article located at the link below that talks about this and at the bottom of the article it also give you an explanation of how to perform a lazy load should you still feel the need.

See "Configuring Lazy Loading in Entity Framework" in this article: Entity Framework and Lazy Loading

Jay
+1  A: 

Don't bind entity types to your UI. This couples the UI to the entity layer. Loading will be the least of your problems. With a coupled UI, you violate the single responsibility principle, require blacklists/whitelists to be maintained to have any form of security, break types which can't deal with circular references, you have poor performance because you load all fields from all related types, etc., etc., etc.

Instead, create a dedicated view model and project onto it:

var pm = (from e in Context.Employees
          where e.Id == id
          select new EmployeePresentation
          {
              EmployeeNumber = e.Number,
              Name = e.Person.Name,
              // etc.
          }.First();

Because this is LINQ to Entities, the fields you reference in Person, etc., are automatically loaded, without requiring eager loading, lazy loading, or explicit Load(). But only those fields, not the entirety of Person, as with every other method.

Update, per comments Using presentation models is also important for updates. It is not the case that I want a user to be able to update every field that they can see. Different presentation models for the same entity might have different validation/scaffolding rules since they're used at different points in data flow within the app. Also, the user should implicitly update fields they cannot see (e.g., timestamp).

Generically, my updates look like this (ASP.MVC Web app):

public ActionResult Update(EmployeePresentation model)
{
    if (!ModelState.IsValid)
    {
        // User violated validation rule on presentation model.
        return View(model);
    }
    Repository.Update(model.Id, delegate(Employee employee) 
    {
        model.UpdateEmployee(employee);
    });
    return RedirectToAction("Index");
}

Note that there is no possibility of the user ever updating something they're not allowed to, in a typechecked, type-safe way, and that the model binding, the presentation model and the repository can all be extended for custom behavior.

Craig Stuntz
Very good. But question is: if you don't bind to entity, then how about the data CUID? you need to write all you own code for CUID. If you bind UI to entity, you can reuse the some code generating engine like ria services. Your solution is for read only data, right?
KentZhou
No, it's not for read-only data. It's *doubly* important for writes. Like I said, without view models, you must whitelist/blacklist user updates, translate user data to entity types, or, worst of all, write an EF-aware UI, the deepest coupling between UI and back end imaginable. I'll update the answer with a clarification.
Craig Stuntz
Craig, I too am interested in your response to the KentZhou's comment. Lets say you have a UI screen that wants to update both the values in the EmployeePresentation object(employee number and the employee name) how do you handle something like that? When passing the presentation back to the service or BLL layer do you just always update both the Employees and the Person table?Do you write different services for when you want to just update an employee vs updating a person record (different views of the data)?
Jay
Actually I do both. See the anonymous delegate above. It's created in the controller but executed by the repository. Hence, the repository has control over what happens before and after the delegate (or even whether to execute the delegate at all), and when/if to actually commit changes to the DB (useful for transactions).
Craig Stuntz
Graig, I think your solution is for asp.net, like MVC, everything is on server side. so there is no server side, client side. What I'm thinking for this issue is for silverlight with ria services based on entity framework. So there is a server side, client side. Association members are not loaded automatically in lazy loading mode.
KentZhou
RIA Services works differently. Lazy loading *will not help* here. You must send fully materialized objects. The **only** way to do this in RIA services is to use the Include attribute. This is unique to RIA services. RIA services is a great tool, but has its own rules. It would be a good idea to specify that you are using RIA services in your questions.
Craig Stuntz