Любые советы о том, как избежать дублирования кода в этой абстракции?

Поэтому я создаю приложение с использованием Entity Framework поверх SQL Compact Edition. Мне не понравилась идея использовать Entites в качестве моих бизнес-объектов, поэтому я строил слой (я назвал его слоем ObjectModel, вероятно, не самая лучшая терминология), который будет брать мои простые объекты, использовать их заполнить и сохранить сущности. А также наоборот - принимать энтузиасты, заполнять POCO для использования в качестве бизнес-объекта


Допустим, у меня есть объект POCO с именем Customer,

public class Customer:ICustomer
    {


        #region ICustomer Members

        public System.Guid id {get;set;}


        public string Forename {get;set;}


        public string Surname { get; set; }


        #endregion
    }

И я хочу заполнить это, используя мой слой ObjectModel. Я в настоящее время делаю это...

OM_Customer<ICustomer,Entity.Customer> customerLayer = new OM_Agent<ICustomer,Entity.Customer>();

ICustomer businessObject = customerLayer.GetById(new Guid("4a75d5a5-6f5a-464f-b4b3-e7807806f1a9"));

Класс OM_Customer наследуется от ObjectModelBase, который ниже.

public abstract class ObjectModelBase<BllClass, EntityClass>
{
    public DataStoreEntities1 db;

    public EntityClass _dataObject;

    public string setName;


    #region POCO-ORM Mapping Functions
    public EntityClass MapBLLToEntity(BllClass bllObject)
    {
        Mapper.CreateMap<BllClass, EntityClass>();
        return Mapper.Map<BllClass, EntityClass>(bllObject);
    }

    public BllClass MapEntityToBLL(EntityClass entityObject)
    {
        Mapper.CreateMap<EntityClass, BllClass>();
        return Mapper.Map<EntityClass, BllClass>(entityObject);
    }
    #endregion

    public void Save(BllClass toAdd)
    {
        _dataObject = MapBLLToEntity(toAdd);

        using (db = new DataStoreEntities1())
        {
            db.AddObject(setName, _dataObject);
            db.SaveChanges();
        }
    }

    public BllClass GetById(Guid id)
    {
        using (db = new DataStoreEntities1())
        {
            EntityClass result = (EntityClass)((object)(from c in  db.CustomerSet  where c.id == id select c).First());
            return MapEntityToBLL(result);
        }

    }

}

Проблема здесь заключается в методе GetById. Метод Save может использоваться подклассами в порядке, поскольку все контексты объектов Entity Framework имеют метод AddObject().

Тем не менее, я хочу иметь общий метод getById, так как все мои сущности будут иметь свойство с именем id (также в db, являющемся первичным ключом). Проблема в том, что здесь linq...

ModelClass result = (ModelClass)((object)(from c in  db.CustomerSet  where c.id == id select c).First());

специфично для db.CustomerSet. Я хочу, чтобы этот абстрактный класс предоставлял общий CRUD/Paging/'Collection Retrieval' для всех моих сущностей, но без повторяющихся нажатий клавиш, однако, этот простой метод GetById заставил меня обратиться за помощью.

Актуальные идеи:

  • чтобы мой get by Id использовал Entity SQL, где у меня был бы больший контроль над созданием строки запроса.
  • удалите структуру сущности и linq, так как для полной абстракции может потребоваться слишком много времени.

Буду признателен за любую информацию о том, как сообщество SO будет решать вышеуказанное.

1 ответ

Решение

Во-первых, я хотел бы начать с вопроса, почему вы чувствуете, что использование EF-сущностей в качестве ваших бизнес-сущностей обязательно было бы плохо? Я сделал это в ряде проектов, и мне еще предстоит столкнуться с серьезными проблемами, которые я не могу преодолеть.

Сказав это, если вы действительно чувствуете, что у вас есть веская причина для разделения двух, вот один из вариантов.

Вы можете использовать делегата, чтобы внедрить конкретный объект набора сущностей для запроса и другой для селектора для ключа - это может позволить производным указывать только свою семантику хранения. Итак, ваш код будет выглядеть так:

public abstract class ObjectModelBase<BllClass, EntityClass>
{
    // ... same basic code here...

    // supplied by your derivatives...
    protected abstract Func<IQueryable<EntityClass>> GetEntitySet { get; };
    protected abstract Func<Guid,Func<EntityClass,bool>> KeySelector { get; }

    public BllClass GetById(Guid id)
    {
        using (db = new DataStoreEntities1())
        {
            EntityClass result = (EntityClass)((object)
                 GetEntitySet()
                     .Where( KeySelector( id ) )
                     .First();
            return MapEntityToBLL(result);
        }
    }
}

public class OM_Customer : ObjectModelBase<ICustomer,Entity.Customer>
{
    protected abstract Func<IQueryable<Entity.Customer>> GetEntitySet
    { 
        get { return db.CustomerSet; }
    }

    protected abstract Func<Guid,Func<Entity.Customer,bool>> KeySelector
    {
        get { return (g => (e => e.Id == g)); }
    }
}
Другие вопросы по тегам