Abstracting Repository

Suppose that I have an object used by my code, say Person:

public class Person {
    public string Name {get;set;}
    public Address Address {get; set;}
}

public class Address {
    public string AddressLine1 {get;set;}
    public string AddressLine2 {get;set;}
    public string City {get;set;}
    public string State {get;set;}
    public string ZipCode {get;set;}
}

Simple so far. Suppose that I persist this object in SQL Server in the following way:

public class PersonEntity {
    public string Name {get;set;}
    public string AddressLine1 {get;set;}
    public string AddressLine2 {get;set;}
    public string City {get;set;}
    public string State {get;set;}
    public string ZipCode {get;set;}
}

Obviously, it is good to abstract how an object is persisted in the DB from the logic. This way, I can replace the way my tables look, or my technology without changing the logic of my solution.

The problem arise if I want to use abstract repository:

public interface IRepository<TEntity>{
    IEnumerable<TEntity> Get(Func<TEntity, bool> pre);
    ...
}

public class PersonRepository<PersonEntity>{
    ...
}

Now, if my business logic code wants to access the repository, they have to know about PersonEntity in order to use the generic Get function. Ideally, the business logic needs to send a request like Get(person => person.Address.State == "NY"); instead.

Is there away, elegant and simple, to achieve that level of abstraction?

Is there away, elegant and simple, to achieve that level of abstraction?

Not really.

You could make a repository for your business objects, but then you’re probably going to need to wire up the Queryable there to just call into the Entity version anyways. Sure something like Automapper might be able to do that but, why bother? I mean, at some point something needs to specify what to look for. EF will already (kinda, sorta) abstract away your data store so that you’re free to change that. But are you really going to change your data entity significantly away from your business object?

What does this abstraction (read: complexity) gain you?

I would say the PersonEntity object is just fluff.

One should be able to get a Person or an Address and have your repository layer do the mapping of logical domain objects to/from database tables. All of that mapping/processing happens in the repository layer.

For example, if switching from SQL to Oracle, I would expect some changes in the mapping layer of the repository but the domain objects (Person/Address) carry forward as is as do the repository interface(s).

So, the application will be the same with changes localized to the repository mapping layer. Business logic and presentation will be untouched. That’s all the abstraction that should be needed.

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *