Using Entity Framework

advertisements

I just started using Entity Framework and it created a Context class which I can use to get all the data i need from it. But I am facing an issue on how I should organize my code, by watching the demos, the person just uses the framework and codes everything on a console application. What is the best way to use Entity Framework and that it looks clean?, what I mean by this is...right now using aspx pages, I could just use the aspx.cs to get the data or save the data. But I do not want this, I would like it to be more organized although the Entity Framework did almost everything by creating the objects etc.. but still, I need to use things like

using(var myobject = new MyContextData())
{
    blah blah..
}

would you say that it would be nicer to write classes that would wrap these calls?. I would really appreciate any inputs as it would really make me a better programmer using the entity framework.

Regards


Edit:

I think that Generic Repository is Anti Pattern. But I do not understand @TomTom comment.

Original Answer:

As Radim Köhler mentioned you need to implement Repository and Unit of Work patterns But the article he provided in my opinion is not fully correct.

At my current job I use following implementation of these patterns. For example, we have three types of entities: Person, Good and Order. I created repository for Persons. In common case Repository must not be generic. It must contain methods which represent specific queries for this entity. So by looking at the interface of repository you can tell what kinds of queries executed for entity (Person, e.g.). As you will see I created DTO for Person called PersonWrap. For creating PersonWrap from Person and updating Person from PersonWrap you can use AutoMapper instead of PersonWrap() constructor and Update() method. Because EntityFramework DbContext implements Unit of Work pattern, you just need to provide created DbContext to repository methods. If repository method is a separate action and you do not need DbContext outside of this method you can create and dispose it inside this method.

public class Person {
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string SecondName { get; set; }
    public DateTime RegistrationDate { get; set; }
    public List<Order> Orders { get; set; }
}

public class Good {
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class Order {
    public int Id { get; set; }
    public Person Person { get; set; }
    public Good Good { get; set; }
    public int Count { get; set; }
}

public class MyDbContext: DbContext
{
    public IDbSet<Person> Persons { get { return Set<Person>(); }}
    public IDbSet<Good> Goods { get { return Set<Good>(); }}
    public IDbSet<Order> Orders { get { return Set<Order>(); }}
}

public class PersonRepository {
    public IEnumerable<Person> GetAll() {
        using (var context = new MyDbContext()) {
            return context.Persons.ToList();
        }
    }

    public IEnumerable<Person> GetLastWeekPersons() {
        using (var context = new MyDbContext()) {
            return context.Persons.Where(p => p.RegistrationDate > new DateTime().AddDays(-7)).ToList();
        }
    } 

    public Person GetById(int id, MyDbContext context) {
        return context.Persons.Include(p => p.Orders).FirstOrDefault(p => p.Id == id);
    }

    public Person GetById(int id) {
        using (var context = new MyDbContext()) {
            return GetById(id, context);
        }
    }
}

public class PersonWrap {
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string SecondName { get; set; }
    public int OrderCount { get; set; }

    public PersonWrap(Person person) {
        Id = person.Id;
        FirstName = person.FirstName;
        SecondName = person.SecondName;
        OrderCount = person.Orders.Count;
    }

    public void Update(Person person) {
        person.FirstName = FirstName;
        person.SecondName = SecondName;
    }
}

public class PersonDetailsViewController {
    public PersonWrap Person { get; protected set; }

    public PersonDetailsViewController(int personId) {
        var person = new PersonRepository().GetById(personId);
        if (person != null) {
            Person = new PersonWrap(person);
        }
    }

    public void Save() {
        using (var context = new MyDbContext()) {
            var person = new PersonRepository().GetById(Person.Id, context);
            Person.Update(person);
            context.SaveChanges();
        }
    }
}