ГЛАВНАЯ     АРХИВ     НАПИСАТЬ АДМИНУ     ПОДПИСАТЬСЯ НА RSS     ВОЙТИ      

Поиск

Категории

Облако тегов

  << Предыдущий пост       Следующий пост >>  
От: inbruk
24. декабря 2014 10:52


C sharp

Очень многие программисты во многих проектах пишут реализацию CRUD для разных сущностей. После того как я написал изрядное количество такого кода и мне надоело решать постоянно похожие задачи. Решений быстрого создания может быть несколько. Наиболее оптимальным, видимо, является генерация с использованием шаблонов T4. У разных подходов есть свои плюсы и минусы. В этом посте расскажу об упрощении создания CRUD для сущности с использованием Generic-ов и библиотеки AutoMapper. Представленное решение, возможно, не завершенное, можно его наверное и улучшить. Но, оно способно существенно ускорить и упростить разработку. Ну или во всяком случае указать направление.

Про библиотеку AutoMapper можно почитать здесь и здесь (производительность и аналоги). Дальше идет код Generic класса для создания CRUD-ов.

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

using NEB.DataAccessLayer;
using AutoMapper;

namespace NEB.BusinessLogicLayer
{
    public abstract class CRUDWithMappingBase<DTO, TBL, TID>  
        where DTO : class 
        where TBL : class
    {
        public CRUDWithMappingBase()
        {
            Mapper.CreateMap<TBL, DTO>();
            Mapper.CreateMap<DTO, TBL>();
        }

        protected TBL _lastCreatedItem = null;

        // получение значения автоинкрементного поля Id при создании одной записи 
        protected abstract TID GetLastCreatedId(); 

        // запись значения Id в DTO объект
        protected abstract void InsertIdInDTO(DTO dtoItem, TID idValue); 

        protected List<DTO> ConvertTBL2DTO(List<TBL> listOfProxy)
        {
            List<DTO> result = new List<DTO>();
            foreach (TBL currProxy in listOfProxy)
            {
                DTO resDTO = Mapper.Map<TBL, DTO>(currProxy);
                result.Add(resDTO);
            }
            return result;
        }

        public void Create(DTO newDTO)
        {
            _lastCreatedItem = Mapper.Map<DTO, TBL>(newDTO);

            try
            {
                NEBEntitiesContext ctx = NEBContextHandler.Get();
                ctx.Set<TBL>().Add(_lastCreatedItem);
                ctx.SaveChanges();
            }
            catch( DbEntityValidationException dbex)
            {
                var errs = dbex.EntityValidationErrors;
                throw dbex; // ловим для поиска ошибки при отладке, но прокидываем, чтобы не скрыть
            }

            TID lastCreatedId = GetLastCreatedId();
            InsertIdInDTO(newDTO, lastCreatedId);
        }

        public void CreateSeveral(List<DTO> newDTOList)
        {
            try
            {
                foreach (DTO currItem in newDTOList)
                {
                    Create(currItem);
                }
            }
            catch (DbEntityValidationException dbex)
            {
                var errs = dbex.EntityValidationErrors;
                throw dbex; // ловим для поиска ошибки при отладке, но прокидываем, чтобы не скрыть
            }
        }

        public void CreateSeveralFastWithoutIdsAquering(List<DTO> newDTOList)
        {
            try
            {
                NEBEntitiesContext ctx = NEBContextHandler.Get();
                foreach (DTO currItem in newDTOList)
                {
                    _lastCreatedItem = Mapper.Map<DTO, TBL>(currItem);
                    ctx.Set<TBL>().Add(_lastCreatedItem);
                }
                ctx.SaveChanges();
            }
            catch (DbEntityValidationException dbex)
            {
                var errs = dbex.EntityValidationErrors;
                throw dbex; // ловим для поиска ошибки при отладке, но прокидываем, чтобы не скрыть
            }
        }

        public List<DTO> ReadAll()
        {
            List<TBL> listOfProxy = NEBContextHandler.Get().Set<TBL>().ToList();
            List<DTO> result = ConvertTBL2DTO(listOfProxy);
            return result;
        }

        protected List<DTO> ReadSeveral(Expression<Func<TBL, bool>> predicate)
        {
            List<TBL> listOfProxy = NEBContextHandler.Get().
                     Set<TBL>().Where(predicate).ToList();

            List<DTO> result = ConvertTBL2DTO(listOfProxy);
            return result;
        }

        protected DTO ReadOne( Expression<Func<TBL, bool>> predicate )
        {
           TBL dataProxyObject = NEBContextHandler.Get().Set<TBL>().SingleOrDefault( predicate );

           DTO resDTO = Mapper.Map<TBL, DTO>(dataProxyObject);
           return resDTO; 
        }

        protected void UpdateOne(DTO upDTO, Expression<Func<TBL, bool>> predicate)
        {
            NEBEntitiesContext ctx = NEBContextHandler.Get();

            TBL dataProxyObject = ctx.Set<TBL>().SingleOrDefault( predicate );
            Mapper.Map<DTO, TBL>(upDTO, dataProxyObject);
            ctx.SaveChanges();        
        }

        protected void DeleteOne(Expression<Func<TBL, bool>> predicate)
        {
            NEBEntitiesContext ctx = NEBContextHandler.Get();
            TBL dataProxyObject = ctx.Set<TBL>().SingleOrDefault(predicate);
            ctx.Set<TBL>().Remove(dataProxyObject);
            ctx.SaveChanges();
        }
        protected void DeleteSeveral(Expression<Func<TBL, bool>> predicate)
        {
            NEBEntitiesContext ctx = NEBContextHandler.Get();
            List<TBL> listOfProxy = ctx.Set<TBL>().Where(predicate).ToList();
            foreach (TBL currProxy in listOfProxy)
            {
                ctx.Set<TBL>().Remove(currProxy);
            }
            ctx.SaveChanges();
        }
    }
}

Здесь DTO - DataTransferObject (он же POC) для передачи данных между BL и верхними слоями, TBL - прокси класс EF, TID - тип колонки (поля) идентификатора записи (строки в БД). А теперь приведен код класса CRUD созданного на основе предыдущего Generic-а. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using SomeProject.BusinessLogicLayer;
using SomeProject.DataAccessLayer;
using DTO = SomeProject.Libraries.BusinessLogicLayer.DataTransferObjects;

namespace SomeProject.Libraries.BusinessLogicLayer
{
    public class LibraryCRUD : CRUDWithMappingBase<DTO.Library, tbl_libraries, Int32> 
    {
        protected override Int32 GetLastCreatedId()
        {
            return _lastCreatedItem.Id;
        }
        protected override void InsertIdInDTO(DTO.Library dtoItem, Int32 idValue)
        {
            dtoItem.Id = idValue;
        }
        public LibraryCRUD() : base() { }
        public DTO.Library ReadOne(Int32 Id) { return this.ReadOne(x => x.Id == Id); }
        public List<DTO.Library> ReadSeveral(List<Int32> listOfIds) 
        { 
            return this.ReadSeveral(x => listOfIds.Contains(x.Id)); 
        }
        public void UpdateOne(DTO.Library lib) { this.UpdateOne(lib, x => x.Id == lib.Id); }
        public void DeleteOne(DTO.Library lib) { this.DeleteOne(lib.Id); }
        public void DeleteOne(Int32 Id) { this.DeleteOne(x => x.Id == Id); }
        public void DeleteSeveral(List<Int32> listOfIds) 
        { 
            this.DeleteSeveral(x => listOfIds.Contains(x.Id)); 
        }
        public DTO.Library ReadOSomeProjectySourceALISIdAndIdFromALIS(Int32 sourceALISId, String idFromALIS) 
        { 
            return this.ReadOne(x => x.SourceALIS == sourceALISId && x.IdFromALIS == idFromALIS); 
        }
        public List<DTO.Library> ReadSeveralBySourceALISIdAndIdFromALISList(
              Int32 sourceALISId, List<String> listOfIds) 
        { 
            return this.ReadSeveral(
                        x => x.SourceALIS == sourceALISId && listOfIds.Contains(x.IdFromALIS)); 
        }
    }
}

Похожие записи


Каким способом удачно сделать выбор совершая покупку между компьютером и ноутбуком
Сейчас купить компьютер в минске, либо в любом ином городишке – не вызовет затруднений. А вот правильно подобрать из многообразия техники не так-то просто и легко. Традиционно, покупатели выбирают из двух типов компьютеров – ноутбук или стационарный компьютер. Между ними существует ряд различий, и у первого и у второго есть много положительных сторон. Подбирать следу...

Вопросы на собеседовании C#, Net, ASP.NET, SQL
Продолжая тему вопросов на собеседовании. Нашел еще одну подборку. Оригинал лежит здесь . Перенес, чтобы не затерялось. Есть вполне вменяемые ответы (хотя, на некоторые вопросы ответил бы по-другому). Ответы находятся после списка вопросов, я их не менял. 23. Что такое шаблон проектирования Model/View/Controller? Как и зачем его применяют? 2...

Как передать функцию как параметр в другую функцию на JavaScript ?
Часто бывают ситуации, когда хочется (было бы удобно) передать функцию как параметр в другую функцию, и там использовать. И все это заметьте на JavaScript-е. Рассмотрим пример того, как это можно сделать. [code:c#] <script type="text/javascript"> function fOne(p1, p2) { p1(p2); } /* function literal */ var fTwo = function (m1) { alert(m1 ...

Добавить комментарий




biuquote
  • Комментарий
  • Предпросмотр
Loading


  Сохранить комментарий