如何映射数据访问业务逻辑实体框架对象 [英] How to map Data Access to Business Logic objects in Entity Framework

查看:196
本文介绍了如何映射数据访问业务逻辑实体框架对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在ASP.NET C#MVC应用程序中使用实体框架。

I am using Entity Framework in an ASP.NET C# MVC application.

我有由EF数据访问层中生成的对象:

I have objects that are generated by EF in the Data Access Layer:

namespace Project1.DataAccess
{
    using System;
    using System.Collections.Generic;

    public partial class User
    {
        public User()
        {
            this.Files = new HashSet<File>();
            this.Folders = new HashSet<Folder>();
        }
        //...

    }
}

现在,我想创建业务逻辑对象,然后与数据访问的人将它们映射:

Now, I want to create Business Logic objects, and then map them with the Data Access ones:

namespace Project1.Logic
{
    public class User
    {
        public int Id { get; set; }
    }
}

我有一个非常小的数字数据库中的表。我是否需要使用 Automapper ?如果没有,我怎么能实现映射?

I have a very small number of tables in the database. Do I need to use Automapper? If no, how can I achieve the mapping?

推荐答案

我用EF6所有的时间来从MSSQL表我的数据访问层,然后创建一组重新present我多么希望交互的对象我的code(或显示它),这是POCO。 映射通过Repository模式的实施照顾。下面是一个通用接口,可以帮助我保证我所有的回购类都遵循相同的形状。

I use EF6 all the time to generate my Data Access Layer from MSSQL tables, then I create a set of objects that represent how I want interact with my code (or display it) which are POCO. The "mapping" is taken care of through the implementation of a Repository pattern. Below is a generic interface that helps me ensure all my repo classes follow the same shape.

    public interface IDataRepository<T>
    {
        IQueryable<T> Get();
        T Get(int id);
        T Add(T obj);
        T Update(T obj);
        void Delete(T obj);
    }

然后,我创建的回购类这样。 (使用UserBusiness和UserDAL班)

Then, I create repo classes like this. (using your UserBusiness and UserDAL classes)

public class NewRepo : IDataRepository<UserBusiness>
{
    YourContext db = new YourContext();

    public IQueryable<UserBusiness> Get()
    {
        return (from u in db.UserDAL select new UserBusiness()
        {
           Id = u.Id,
           Name = u.Name
        });
    }

    public UserBusiness Get(int id)
    {
        return (from u in db.UserDAL where u.Id == id select new UserBusiness()
        {
           Id = u.Id,
           Name = u.Name
        }).FirstOrDefault();
    }

    public Order Add(UserBusiness obj)
    {
        UserDAL u= new UserDAL();
        u.Name = obj.Name;

        db.UserDAL.Add(u);
        db.SaveChanges();

        //Assuming the database is generating your Id's for you
        obj.Id = u.Id;

        return obj;

    }

    public Order Update(UserBusiness obj)
    {
        UserDAL u= new UserDAL();
        u.Id = obj.Id;
        u.Name = obj.Name;

        db.Entry(u).State = EntityState.Modified;
        db.SaveChanges();

        return obj;
    }

    public void Delete(UserBusiness obj)
    {
        UserDAL u = db.UserDAL
            .Where(o=>o.Id == obj.Id)
            .FirstOrDefault();

        if (u!=Null)  {
          db.Entry(u).State = EntityState.Deleted;
          db.SaveChanges();
        }

    }
}

从您的应用程序中,你现在用你的回购类的方法,而不是你的DbContext的。

From within your application, you'd now use the methods of your repo class instead of your DBContext.

最后,我最后往往将服务类与我的回购其管理业务类的内部数据交互的另一层...或者你可以让你的商务类'聪明'加入回购的方法来他们。我的preference是保持POCO的愚蠢,并建立服务类获取,设置和编辑属性。

Lastly, I often end up adding another layer of 'Service Classes' that interact with my repos which manage the internal data of the Business classes...or you could make your Business classes 'smarter' by adding the repo methods to them. My preference is to keep POCO's dumb and build service classes to get, set and edit properties.

是的,有一堆左右映射转换一类到另一个,但它的内部业务逻辑类,为以后完全分离。直表POCO转换似乎傻起初,只是等待,直到你的DBA想要的正常化几个字段,或者你决定要一个集合添加到这些简单的对象。如果能够不破坏你的应用程序的其余部分是无价的管理你的业务对象。

Yes, there is a bunch of left-right mapping to "convert" one class to another, but it's a clean separation of internal business logic classes for later on. Straight table to POCO conversions seems silly at first, but just wait until your DBA want's to normalize a few fields or you decide to add a collection to those simple objects. Being able to manage your business objects without breaking the rest of you app is priceless.

编辑:的下面有资源库,这使得创建新库轻松了许多通用版

Below there is generic version of the Repository, which makes creating new repositories a lot easier.

所有业务逻辑层类这是基类:

This is base class for all Business Logic Layer classes:

public class BaseEntity
{
    public int Id { get; set; }
}

这是所有数据访问层类的基类:

This is base class for all Data Access Layer classes:

public class BaseEntityDAL
{
    [Key]
    [Column("Id")]
    public int Id { get; set; }
}

这是库通用基础类(注意,我们使用AutoMapper这里):

This is generic base class for repository (note, that we use AutoMapper here):

public abstract class BaseRepository<TDAL, TBLL> : IRepository<TBLL>
    where TDAL : BaseEntityDAL, new()
    where TBLL : BaseEntity, new()
{
    protected readonly MyDbContext context;
    protected readonly DbSet<TDAL> dbSet;

    protected virtual TDAL Map(TBLL obj)
    {
        Mapper.CreateMap<TBLL, TDAL>();
        return Mapper.Map<TDAL>(obj);
    }

    protected virtual TBLL Map(TDAL obj)
    {
        Mapper.CreateMap<TDAL, TBLL>();
        return Mapper.Map<TBLL>(obj);
    }

    protected abstract IQueryable<TBLL> GetIQueryable();            

    public BaseRepository(MyDbContext context, DbSet<TDAL> dbSet)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));
        if (dbSet == null)
            throw new ArgumentNullException(nameof(dbSet));

        this.context = context;
        this.dbSet = dbSet;
    }

    public TBLL Get(int id)
    {
        var entity = dbSet
            .Where(i => i.Id == id)
            .FirstOrDefault();

        var result = Map(entity);

        return result;
    }

    public IQueryable<TBLL> Get()
    {
        return GetIQueryable();
    }

    public TBLL Add(TBLL obj)
    {
        var entity = Map(obj);

        dbSet.Add(entity);
        context.SaveChanges();

        obj.Id = entity.Id;

        return obj;
    }

    public TBLL Update(TBLL obj)
    {
        var entity = Map(obj);

        context.Entry(entity).State = EntityState.Modified;
        context.SaveChanges();

        return obj;
    }

    public void Delete(TBLL obj)
    {
        TDAL entity = dbSet
            .Where(e => e.Id == obj.Id)
            .FirstOrDefault();

        if (entity != null)
        {
            context.Entry(entity).State = EntityState.Deleted;
            context.SaveChanges();
        }
    }
}

最后,当我们得到了所有以上,这是库的样本实现,非常干净的:

Finally, when we got all above, this is sample implementation of repository, nice and clean:

public class ContractRepository : BaseRepository<ContractDAL, Contract>
{
    protected override IQueryable<Contract> GetIQueryable()
    {
        return dbSet
            .Select(entity => new Contract()
            {
                // We cannot use AutoMapper here, because Entity Framework
                // won't be able to process the expression. Hence manual
                // mapping.
                Id = entity.Id,
                CompanyId = entity.CompanyId,
                ProjectId = entity.ProjectId,
                IndexNumber = entity.IndexNumber,
                ContractNumber = entity.ContractNumber,
                ConclusionDate = entity.ConclusionDate,
                Notes = entity.Notes
            });
    }

    public ContractRepository(MyDbContext context)
        : base(context, context.Contracts)
    {

    }
}

这篇关于如何映射数据访问业务逻辑实体框架对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆