我试图使用实体框架实现分层应用程序,并使用 DTO 在层之间传递对象。
我一直在通过一些在线代码来设置一个通用存储库,但我遇到了一些我无法解决的方法。
我使用 EntitiesToDTOs 从 edmx 文件生成我的 DTO,但不幸的是它们没有基类(手动更新的太多了)
为了设置场景,我有以下 2 个通用类:
存储库:
public interface IRepository<TEntity> : IDisposable
{
/// <summary>
/// Creates a new empty entity.
/// </summary>
TEntity Create();
/// <summary>
/// Creates the existing entity.
/// </summary>
TEntity Create(TEntity entity);
/// <summary>
/// Updates the existing entity.
/// </summary>
TEntity Update(TEntity entity);
/// <summary>
/// Delete an entity using its primary key.
/// </summary>
void Delete(long id);
/// <summary>
/// Delete the given entity.
/// </summary>
void Delete(TEntity entity);
/// <summary>
/// Deletes the existing entity.
/// </summary>
void Delete(Expression<Func<TEntity, bool>> where);
/// <summary>
/// Finds one entity based on provided criteria.
/// </summary>
TEntity FindOne(Expression<Func<TEntity, bool>> where = null);
/// <summary>
/// Finds one entity based on its Identifier.
/// </summary>
TEntity FindById(long id);
/// <summary>
/// Finds entities based on provided criteria.
/// </summary>
IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null);
/// <summary>
/// Finds other related entities based of type T for queries.
/// </summary>
IQueryable<T> Set<T>() where T : class;
/// <summary>
/// Save any changes to the TContext
/// </summary>
bool SaveChanges();
}
通用实现:
public class Repository<TEntity, TContext> : IRepository<TEntity>, IDisposable
where TEntity : class
where TContext : DbContext
{
protected TContext Context;
public Repository(DbContext dbContext)
{
Context = dbContext as TContext;
}
public virtual TEntity Create()
{
return Context.Set<TEntity>().Create();
}
public virtual TEntity Create(TEntity entity)
{
return Context.Set<TEntity>().Add(entity);
}
public virtual TEntity Update(TEntity entity)
{
Context.Entry(entity).State = EntityState.Modified;
return entity;
}
public virtual void Delete(long id)
{
var item = Context.Set<TEntity>().Find(id);
Context.Set<TEntity>().Remove(item);
}
public virtual void Delete(TEntity entity)
{
Context.Set<TEntity>().Remove(entity);
}
public virtual void Delete(Expression<Func<TEntity, bool>> where)
{
var objects = Context.Set<TEntity>().Where(where).AsEnumerable();
foreach (var item in objects)
{
Context.Set<TEntity>().Remove(item);
}
}
public virtual TEntity FindById(long id)
{
return Context.Set<TEntity>().Find(id);
}
public virtual TEntity FindOne(Expression<Func<TEntity, bool>> where = null)
{
return FindAll(where).FirstOrDefault();
}
public IQueryable<T> Set<T>() where T : class
{
return Context.Set<T>();
}
public virtual IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null)
{
return null != where ? Context.Set<TEntity>().Where(where) : Context.Set<TEntity>();
}
public virtual bool SaveChanges()
{
return 0 < Context.SaveChanges();
}
/// <summary>
/// Releases all resources used by the Entities
/// </summary>
public void Dispose()
{
if (null != Context)
{
Context.Dispose();
}
}
}
用于在 Order 记录和 Order DTO 之间转换的类:
/// <summary>
/// Assembler for <see cref="Order"/> and <see cref="OrderDTO"/>.
/// </summary>
public static partial class OrderAssembler
{
/// <summary>
/// Invoked when <see cref="ToDTO"/> operation is about to return.
/// </summary>
/// <param name="dto"><see cref="OrderDTO"/> converted from <see cref="Order"/>.</param>
static partial void OnDTO(this Order entity, OrderDTO dto);
/// <summary>
/// Invoked when <see cref="ToEntity"/> operation is about to return.
/// </summary>
/// <param name="entity"><see cref="Order"/> converted from <see cref="OrderDTO"/>.</param>
static partial void OnEntity(this OrderDTO dto, Order entity);
/// <summary>
/// Converts this instance of <see cref="OrderDTO"/> to an instance of <see cref="Order"/>.
/// </summary>
/// <param name="dto"><see cref="OrderDTO"/> to convert.</param>
public static Order ToEntity(this OrderDTO dto)
{
if (dto == null) return null;
var entity = new Order();
entity.OrderID = dto.OrderID;
entity.SupplierID = dto.SupplierID;
entity.Special = dto.Special;
entity.RequestedBy = dto.RequestedBy;
entity.RequestedFor = dto.RequestedFor;
entity.Urgent = dto.Urgent;
entity.OrderStatus = dto.OrderStatus;
entity.DeliveryAddressID = dto.DeliveryAddressID;
entity.OrderDate = dto.OrderDate;
entity.Deleted = dto.Deleted;
entity.SentToSage = dto.SentToSage;
entity.Cancelled = dto.Cancelled;
entity.InvoiceAddressID = dto.InvoiceAddressID;
entity.SageOrderID = dto.SageOrderID;
entity.SageDatabaseID = dto.SageDatabaseID;
entity.DeliveryDate = dto.DeliveryDate;
entity.SupplierReference = dto.SupplierReference;
entity.Analysis1 = dto.Analysis1;
entity.Analysis2 = dto.Analysis2;
entity.Analysis3 = dto.Analysis3;
entity.Analysis4 = dto.Analysis4;
entity.Analysis5 = dto.Analysis5;
entity.Analysis6 = dto.Analysis6;
entity.OrderDiscount = dto.OrderDiscount;
entity.SageDatabaseName = dto.SageDatabaseName;
entity.SupplierName = dto.SupplierName;
entity.RequestedByName = dto.RequestedByName;
entity.DeliveryAddressName = dto.DeliveryAddressName;
entity.NetValue = dto.NetValue;
entity.DepartmentID = dto.DepartmentID;
entity.PODocumentNo = dto.PODocumentNo;
entity.ConstructRelated = dto.ConstructRelated;
entity.Archived = dto.Archived;
entity.UpdateStatus = dto.UpdateStatus;
entity.UpdatedDate = dto.UpdatedDate;
entity.UpdatedUser = dto.UpdatedUser;
entity.WarehouseID = dto.WarehouseID;
entity.ExchangeRate = dto.ExchangeRate;
entity.CurrencySymbol = dto.CurrencySymbol;
entity.SupplierEmailAddress = dto.SupplierEmailAddress;
entity.SupplierContactName = dto.SupplierContactName;
entity.SupplierTelephone = dto.SupplierTelephone;
entity.SupplierFax = dto.SupplierFax;
entity.HasAttachments = dto.HasAttachments;
entity.HasAnalysisValues = dto.HasAnalysisValues;
entity.SYSTraderAnalysisValueID = dto.SYSTraderAnalysisValueID;
entity.InternalOrder = dto.InternalOrder;
entity.DeliveryPostalName = dto.DeliveryPostalName;
entity.DeliveryAddressLine1 = dto.DeliveryAddressLine1;
entity.DeliveryAddressLine2 = dto.DeliveryAddressLine2;
entity.DeliveryAddressLine3 = dto.DeliveryAddressLine3;
entity.DeliveryAddressLine4 = dto.DeliveryAddressLine4;
entity.DeliveryPostCode = dto.DeliveryPostCode;
entity.InvoicePostalName = dto.InvoicePostalName;
entity.InvoiceAddressLine1 = dto.InvoiceAddressLine1;
entity.InvoiceAddressLine2 = dto.InvoiceAddressLine2;
entity.InvoiceAddressLine3 = dto.InvoiceAddressLine3;
entity.InvoiceAddressLine4 = dto.InvoiceAddressLine4;
entity.InvoicePostCode = dto.InvoicePostCode;
entity.DeliveryContactName = dto.DeliveryContactName;
entity.InvoiceContactName = dto.InvoiceContactName;
entity.DeliveryTelephoneNo = dto.DeliveryTelephoneNo;
entity.DeliveryFaxNo = dto.DeliveryFaxNo;
entity.InvoiceTelephoneNo = dto.InvoiceTelephoneNo;
entity.InvoiceFaxNo = dto.InvoiceFaxNo;
entity.CheckForNewDocuments = dto.CheckForNewDocuments;
entity.EmailSent = dto.EmailSent;
entity.DocumentNoPrefix = dto.DocumentNoPrefix;
dto.OnEntity(entity);
return entity;
}
/// <summary>
/// Converts this instance of <see cref="Order"/> to an instance of <see cref="OrderDTO"/>.
/// </summary>
/// <param name="entity"><see cref="Order"/> to convert.</param>
public static OrderDTO ToDTO(this Order entity)
{
if (entity == null) return null;
var dto = new OrderDTO();
dto.OrderID = entity.OrderID;
dto.SupplierID = entity.SupplierID;
dto.Special = entity.Special;
dto.RequestedBy = entity.RequestedBy;
dto.RequestedFor = entity.RequestedFor;
dto.Urgent = entity.Urgent;
dto.OrderStatus = entity.OrderStatus;
dto.DeliveryAddressID = entity.DeliveryAddressID;
dto.OrderDate = entity.OrderDate;
dto.Deleted = entity.Deleted;
dto.SentToSage = entity.SentToSage;
dto.Cancelled = entity.Cancelled;
dto.InvoiceAddressID = entity.InvoiceAddressID;
dto.SageOrderID = entity.SageOrderID;
dto.SageDatabaseID = entity.SageDatabaseID;
dto.DeliveryDate = entity.DeliveryDate;
dto.SupplierReference = entity.SupplierReference;
dto.Analysis1 = entity.Analysis1;
dto.Analysis2 = entity.Analysis2;
dto.Analysis3 = entity.Analysis3;
dto.Analysis4 = entity.Analysis4;
dto.Analysis5 = entity.Analysis5;
dto.Analysis6 = entity.Analysis6;
dto.OrderDiscount = entity.OrderDiscount;
dto.SageDatabaseName = entity.SageDatabaseName;
dto.SupplierName = entity.SupplierName;
dto.RequestedByName = entity.RequestedByName;
dto.DeliveryAddressName = entity.DeliveryAddressName;
dto.NetValue = entity.NetValue;
dto.DepartmentID = entity.DepartmentID;
dto.PODocumentNo = entity.PODocumentNo;
dto.ConstructRelated = entity.ConstructRelated;
dto.Archived = entity.Archived;
dto.UpdateStatus = entity.UpdateStatus;
dto.UpdatedDate = entity.UpdatedDate;
dto.UpdatedUser = entity.UpdatedUser;
dto.WarehouseID = entity.WarehouseID;
dto.ExchangeRate = entity.ExchangeRate;
dto.CurrencySymbol = entity.CurrencySymbol;
dto.SupplierEmailAddress = entity.SupplierEmailAddress;
dto.SupplierContactName = entity.SupplierContactName;
dto.SupplierTelephone = entity.SupplierTelephone;
dto.SupplierFax = entity.SupplierFax;
dto.HasAttachments = entity.HasAttachments;
dto.HasAnalysisValues = entity.HasAnalysisValues;
dto.SYSTraderAnalysisValueID = entity.SYSTraderAnalysisValueID;
dto.InternalOrder = entity.InternalOrder;
dto.DeliveryPostalName = entity.DeliveryPostalName;
dto.DeliveryAddressLine1 = entity.DeliveryAddressLine1;
dto.DeliveryAddressLine2 = entity.DeliveryAddressLine2;
dto.DeliveryAddressLine3 = entity.DeliveryAddressLine3;
dto.DeliveryAddressLine4 = entity.DeliveryAddressLine4;
dto.DeliveryPostCode = entity.DeliveryPostCode;
dto.InvoicePostalName = entity.InvoicePostalName;
dto.InvoiceAddressLine1 = entity.InvoiceAddressLine1;
dto.InvoiceAddressLine2 = entity.InvoiceAddressLine2;
dto.InvoiceAddressLine3 = entity.InvoiceAddressLine3;
dto.InvoiceAddressLine4 = entity.InvoiceAddressLine4;
dto.InvoicePostCode = entity.InvoicePostCode;
dto.DeliveryContactName = entity.DeliveryContactName;
dto.InvoiceContactName = entity.InvoiceContactName;
dto.DeliveryTelephoneNo = entity.DeliveryTelephoneNo;
dto.DeliveryFaxNo = entity.DeliveryFaxNo;
dto.InvoiceTelephoneNo = entity.InvoiceTelephoneNo;
dto.InvoiceFaxNo = entity.InvoiceFaxNo;
dto.CheckForNewDocuments = entity.CheckForNewDocuments;
dto.EmailSent = entity.EmailSent;
dto.DocumentNoPrefix = entity.DocumentNoPrefix;
entity.OnDTO(dto);
return dto;
}
/// <summary>
/// Converts each instance of <see cref="OrderDTO"/> to an instance of <see cref="Order"/>.
/// </summary>
/// <param name="dtos"></param>
/// <returns></returns>
public static List<Order> ToEntities(this IEnumerable<OrderDTO> dtos)
{
if (dtos == null) return null;
return dtos.Select(e => e.ToEntity()).ToList();
}
/// <summary>
/// Converts each instance of <see cref="Order"/> to an instance of <see cref="OrderDTO"/>.
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
public static List<OrderDTO> ToDTOs(this IEnumerable<Order> entities)
{
if (entities == null) return null;
return entities.Select(e => e.ToDTO()).ToList();
}
}
我对“OrderRepository”的实现:
public class OrderRepository : IRepository<OrderDTO>
{
private Repository<Order, WAPEntities> _repository;
public OrderRepository()
{
_repository = new Repository<Order, WAPEntities>(new WAPEntities());
}
public void Dispose()
{
_repository.Dispose();
}
public OrderDTO Create()
{
return _repository.Create().ToDTO();
}
public OrderDTO Create(OrderDTO entity)
{
return _repository.Create(entity.ToEntity()).ToDTO();
}
public OrderDTO Update(OrderDTO entity)
{
return _repository.Update(entity.ToEntity()).ToDTO();
}
public void Delete(long id)
{
_repository.Delete(id);
}
public void Delete(OrderDTO entity)
{
_repository.Delete(entity.ToEntity());
}
public void Delete(Expression<Func<OrderDTO, bool>> where)
{
// I have tried this but it wont work
var resultBody = Expression.Convert(where.Body, typeof(OrderDTO));
var result = Expression.Lambda<Func<Order, bool>>(resultBody, where.Parameters);
_repository.Delete(result);
}
public OrderDTO FindOne(System.Linq.Expressions.Expression<Func<OrderDTO, bool>> where = null)
{
//Here the same issue with the Where clause
throw new NotImplementedException();
}
public OrderDTO FindById(long id)
{
return _repository.FindById(id).ToDTO();
}
public IQueryable<OrderDTO> FindAll(System.Linq.Expressions.Expression<Func<OrderDTO, bool>> where = null)
{
//Here the same issue with the Where clause
throw new NotImplementedException();
}
public IQueryable<T> Set<T>() where T : class
{
return _repository.Set<T>();
}
public bool SaveChanges()
{
return _repository.SaveChanges();
}
}
如您所见,对于我的大多数 Order Repository 方法,我可以非常轻松地将实体从实体转换为 DTO,并且从 DTO 转换为实体。
我正在苦苦挣扎的是如何将 lamda where 子句转换为从接受我的 Order DTO 类的 lambda 转换,并在其上调用 entity.ToDTO() 并转换为订单实体的 lambda。
我无法解决的方法是:
public void Delete(Expression<Func<OrderDTO, bool>> where)
public OrderDTO FindOne(System.Linq.Expressions.Expression<Func<OrderDTO, bool>> where = null)
public IQueryable<OrderDTO> FindAll(System.Linq.Expressions.Expression<Func<OrderDTO, bool>> where = null)
这甚至可能吗?