1

I am using entity framework to get a IEnumerable<CustomersEntity>, and I need to cast this to a IEnumerable<CustomerBO> to display it in some view. I know how to do cast a IEnumerable<T1> to a IEnumerable<T2>; but in this case, who will be in charge of it ? I thought CustomerBO could do it, but is it correct for an object return a list of itself ? or have I to write a layer with only one function ? I am in a MVC project, so maybe the controller could be involved; but if possible I prefer to decouple it from the DAL...

Here is what I currently have:

Entity :

public class CustomerEntity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public IEnumerable<Invoices> Invoices { get; set; }
}

And Business object:

public class CustomerBO
{
    public string FullName { get; set; }
    public string FullAddress { get; set; }
    public string InvoicesNumber { get; set; }
    public string InvoicesTotalAmount { get; set; }

    public CustomerBO(CustomerEntity customer)
    {
        //Instanciate the object
    }
}

Note I need a one-way only process; I won't have to insert a CustomerBO in the database.

  • 4
    The consumer always takes care of the conversion. The object being consumed doesn't know how it's being consumed or who is going to consume it, and should be kept as simple as possible. That being said, your BO having a constructor receiving the entity is a valid way to do it. – Machado Jun 16 '17 at 13:19
  • I am not familiar with entity-framework, but is this framework provide things like lazy-loading (like Hibernate/JPA for Java) too ? If so you might need to think carefully about how to handle this. Personnaly I went for the same object so I don't have to duplicate things and convert them. – Walfrat Jun 16 '17 at 13:20
  • @Machado "The consumer always takes care of the conversion" absolutely, but I am in a MVC project, and I'lI prefer to decouple it from the DAL. Until now I worked with entities directly, or single instances of business objects; never with lists of them. – gobes Jun 16 '17 at 13:24
  • @Walfrat Yes, entity framework natively implements lazy-loading; when I wrote List in my question, I meant IEnumerable, which allow to do lazy loading efficiently. I'll edit my question to reflect this. – gobes Jun 16 '17 at 13:29
  • @gobes, I'm not sure I understood correctly, then. Your Entity is on the DAL and your BO is on the MVC project ? Is this correct ? – Machado Jun 16 '17 at 14:02
2

Your CustomerBO class should have NO reference to the EF entity. This conversion should take place in side a repository. If the business object has any reference to the entity, it is still coupled to the database, and it can be difficult to run simulations, "what-if-scenarios" ect, independent of your data if you need to.

public class CustomerRepository
{
     // dont forget to close your connections, which I left out...
     public CustomerBO GetCustomer(id)
     {
          return Map(DBContext.Customers.Where(c => c.Id == id).Single());
     }

     public IEnumerable<CustomerBO> GetAllCustomers()
     {
          return Map(DBContext.Customers.Select(c => Map(c));
     }

     private CustomerBO Map(CustomerEntity entity)
     {
          CustomerBo bo = new CustomerBO();
          bo.FirstName = entity.FirstName;
          //etc
          bo.InvoicesNumber = entity.invoices.Count();
          bo.InvoicesTotalAmount = entity.invoices.select(i => i.Amount).Sum();
     }


}

You may think, this seems slow, but do not be tempted by the siren of premature optimization. Also, if you are very concerned about speed, you should use Dapper.net instead of entity framework.

You then call the repository from your controller, and map the BO to the view model in the controller, or just use the BO directly if it suits your purposes.

There is still coupling inside the repository, but it is limited to only there, so if you need to change your DB, you only have to change it one place

| improve this answer | |
  • 1
    That's funny, I ended up with a similar solution, but with DI to allow unit testing. And I totally agree with your statement about CustomerBO not having any references to EF and Dapper; but speed is not at all a priority :) – gobes Jun 16 '17 at 19:52
  • btw, if you want to get very pedantic, the repository should not do the summing... that is considered business logic and should be handled by CustomerBO or an InvoiceCollection class – TheCatWhisperer Jun 16 '17 at 20:17
  • 1
    Yes, but it was just an simplified exemple, not real code nor an exactly real situation ;) – gobes Jun 18 '17 at 19:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.