如何将数据访问映射到实体框架中的业务逻辑对象

2024-03-12

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

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

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>();
        }
        //...

    }
}

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

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

我的数据库中有很少数量的表。我需要使用吗Automapper?如果没有,我怎样才能实现映射?


我一直使用 EF6 从 MSSQL 表生成数据访问层,然后创建一组对象来表示我希望如何与 POCO 代码交互(或显示它)。 “映射”是通过存储库模式的实现来处理的。下面是一个通用界面,可帮助我确保所有存储库类都遵循相同的形状。

    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 类)

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。

最后,我经常最终添加另一层“服务类”,它与我的存储库交互,管理业务类的内部数据……或者您可以通过向它们添加存储库方法来使您的业务类“更智能”。我的偏好是保持 POCO 的愚蠢并构建服务类来获取、设置和编辑属性。

是的,有一堆左右映射可以将一个类“转换”为另一个类,但它是内部业务逻辑类的清晰分离,供以后使用。直接表到 POCO 的转换一开始看起来很愚蠢,但只要等到您的 DBA 想要规范化一些字段或者您决定向这些简单对象添加集合即可。能够在不破坏应用程序其余部分的情况下管理您的业务对象是无价的。


Edit:下面是存储库的通用版本,这使得创建新存储库变得更加容易。

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

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

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

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

这是存储库的通用基类(注意,我们在这里使用 AutoMapper):

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();
        }
    }
}

最后,当我们完成以上所有内容后,这是存储库的示例实现,漂亮而干净:

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)
    {

    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将数据访问映射到实体框架中的业务逻辑对象 的相关文章

  • C++ 有像 Pascal 一样的“with”关键字吗?

    withPascal 中的关键字可用于快速访问记录的字段 有人知道 C 是否有类似的东西吗 前任 我有一个包含许多字段的指针 但我不想这样输入 if pointer gt field1 pointer gt field2 pointer g
  • 何时对向量进行归一化?

    我正在学习 XNA 并且在几乎所有的教育套件中都可以找到http creators xna com en US http creators xna com en US 我总是看到向量上对 Normalize 的调用 我知道归一化基本上将向量
  • 如何将 C++ 类包装在基于 C 的 dll 或基于 CLI 的 dll 中?

    我被告知将我用 C 编写的类导入到 dll 中 然后在 c 应用程序中使用该 dll 下列的本指南 https stackoverflow com questions 4555961 how to use a class in dll我创建
  • C++ - 模板专业化和部分专业化

    我一直在互联网和 stackoverflow 上寻找具体的答案 但我似乎找不到 我必须创建一个通用类 然后实现特定的功能 我的具体说明是 您需要使用模板表达式参数以及模板类专业化和部分专业化 我有一个模板类 template
  • 使用 QSet 作为 Qt 地图容器中的键

    我需要一个映射 其中键是唯一的 并且每个键都是一组或自定义 POD 结构 其中包含 3 个数据项 这些值只是指向对象实例的指针 从阅读Qt 的 QMap 与 QHash 的文档 http qt project org doc qt 4 8
  • 隐形打开的弹出窗口

    第二天就解决这个问题 要重现 请创建新的 WPF 应用程序 xaml
  • TestMethod:异步任务 TestSth() 不适用于 .NET 4.0

    我正在尝试使用 NET 4 0 BCL Async 和 MsTest 运行异步测试方法 看来这个设置不能处理 测试方法 异步Task测试Sth 由于测试用例资源管理器中缺少条目 将签名更改为异步后void 我可以运行测试用例 但结果错误 根
  • 实体框架7审计日志

    我正在将一个旧项目移植到 ASP NET 5 和 Entity Framework 7 我使用数据库优先方法 DNX 脚手架 来创建模型 旧项目基于Entity Framework 4 审计跟踪是通过重写实现的SaveChanges的方法D
  • Windows 程序如何临时更改其时区?

    我写了一个函数来返回time t与给定日期的午夜相对应的值 当给定日期没有午夜时 它返回最早可用的时间 例如 当埃及进入夏令时时 这种情况就可能发生 今年 时间更改于 4 月 29 日晚上午夜生效 因此时钟直接从 23 59 转到 01 0
  • 使用 Microsoft Graph 创建用户

    如何使用 Microsoft graph 创建用户 因为我在保存过程中遇到了权限失败的问题 我确实有几个问题 在图中调用创建用户 API 将在哪里创建用户 是在 Azure AD 还是其他地方 我尝试通过传递 json 和必需的标头来调用创
  • 从 ef core 的子集合中删除一些项目

    我有一个父表和子表 其中父表与子表具有一对多关系 我想删除一些子项 并且希望父项的子集合反映该更改 如果我使用删除选定的子项RemoveRange 那么子集合不会更新 如果我使用Remove从子集合中删除子集合然后 显然 它不如使用效率高R
  • 使用对象列表构建树

    我有一个带有属性 id 和parent id 的对象列表 我想建造一棵树来连接那些孩子和父母 1 个父对象可以有多个子对象 并且有一个对象将成为所有对象的祖先 实现该功能最快的算法是什么 我使用 C 作为编程语言 但其他语言也可以 像这样的
  • AspNetCore.SignalR:无法启动未处于初始状态的连接

    我无法让 ASP NET Core SignalR 应用程序正常运行 我有这个服务器端代码 public class PopcornHub Hub private int Users public async Task BroadcastN
  • IEnumerable.比带中断的 for 循环更快吗?

    我们的代码打开表单时遇到了一些缓慢的情况 这可能是由于for循环与break这需要很长时间才能执行 我把它切换到IEnumerable Any 并看到表格很快打开 我现在试图弄清楚是否单独进行此更改会提高性能 或者是否正在访问Product
  • Unity 2.0 和处理 IDisposable 类型(特别是使用 PerThreadLifetimeManager)

    我知道类似的问题被问过好几次 例如 here https stackoverflow com questions 987761 how do you reconcile idisposable and ioc here https stac
  • 向每个收件人发送一封包含不同内容的电子邮件(使用抄送字段)

    在你因为这个问题 毫无意义 和 不可能 而驳回之前 请听我说完 问题 我们在使用我们的系统发送的每封电子邮件中实施跟踪像素 即具有唯一 URL 的可下载 GIF 文件 这有助于我们跟踪电子邮件的打开情况 问题是 当我们抄送一些收件人时 跟踪
  • C 中的静态和动态绑定(严格来说是 C,而不是 C++)是什么?

    我最初对发布这个问题感到担忧 以免它重复 但即使在谷歌搜索了许多关键字之后 我在 StackOverflow 上找不到任何解释 C 的静态和动态绑定的链接 尽管有 C 的问题和答案 但是都涉及classes以及显然不适合 C 的东西 Sta
  • Visual Studio 2015默认附加库

    当我在 VS 2015 中创建一个空项目时 它会自动将这些库放入 附加依赖项 中 kernel32 lib user32 lib gdi32 lib winspool lib comdlg32 lib advapi32 lib shell3
  • 计算两个日期之间的工作日数?

    在C 中 如何计算business 或工作日 两个日期之间的天数 我以前曾经遇到过这样的任务 并且我已经找到了解决方案 当可以避免的时候 我会避免列举其间的所有日子 这里就是这种情况 正如我在上面的一个答案中看到的那样 我什至没有提到创建一
  • 如何设置 Swashbuckle 与 Microsoft.AspNetCore.Mvc.Versioning

    我们有asp net core webapi 我们添加了Microsoft AspNetCore Mvc Versioning and Swashbuckle拥有招摇的用户界面 我们将控制器指定为 ApiVersion 1 0 Route

随机推荐

  • 为什么 chunk_while 返回 Enumerator 对象

    为什么chunk while返回一个实例Enumerator 这段代码 array 0 1 2 3 4 5 7 8 9 15 16 p array chunk while i j i 1 j 输出这个
  • SQL Server 全文搜索包含连字符的短语不返回预期结果

    我们有一个使用 SQL Server 2008 数据库和全文搜索的应用程序 我试图理解为什么以下搜索的行为不同 首先 一个包含连字符的单词的短语 如下所示 contains column name one two three four fi
  • 有什么方法可以通过查询自省来读取类型上的 GraphQL 指令吗?

    对于身份验证等用例 可以将自定义指令添加到 GraphQL 模式 如文档中所示 https www graphql java com documentation v16 sdl directives https www graphql ja
  • 使用 C# 求解偏微分方程

    我正在开发一个项目 C 和 NET Framework 该项目需要我求解一些偏微分方程 是否有任何基于 NET Framework 的特定库可供我查看并简化我的工作 我使用过 MATLAb 求解偏微分方程非常简单 我怎么解决这个问题 取决于
  • 如何在控制器之间共享通用逻辑?

    我有两个页面和两个控制器 可以对同一数据集执行搜索 有一种简单的形式来指定搜索条件 另一个允许用户在地图上选择数据 通过选择区域或单击地图上的要素 然后 搜索结果将显示在搜索控件下方 同一页面上 的数据表中 因此 控制器具有不同的搜索功能
  • 添加自签名 SSL 证书而不禁用权威机构签名的证书

    我有一个公司 git 服务器 使用自签名证书通过 https 工作 本地克隆包含两个遥控器 一个指向该服务器的源 另一个指向 github 默认情况下 从原点拉取失败 git pull fatal unable to access http
  • 我提交的这些图标是什么

    我最近开始从事项目工作 并使用 Windows 版 Github 提交并推送它 但如果你看看 gitignore 有一个 camel and a boom 提交旁边的图标 这些有什么目的吗 它们似乎是由 Github for Windows
  • 如何迭代 Rails 应用程序中的所有模型?

    我希望能够迭代并检查 Rails 应用程序中的所有模型 在伪代码中 它看起来像 rails env models each do model associations model reflect on all associations ha
  • 语言识别和自动文本框方向切换

    假设我有一个 HTML 文本框 使用以下代码
  • Android TextView 中如何调整文本字距?

    Android 有没有办法调整字符间距TextView 我相信这通常称为 字距调整 我知道android textScaleX属性 但是会压缩字符以及间距 我构建了一个扩展 TextView 并添加方法 setSpacing 的自定义类 解
  • 人类可读、递归、排序的最大文件列表

    在 POSIX shell 中打印前 10 个最大文件列表的最佳实践是什么 必须有比我当前的解决方案更优雅的东西 DIR N 10 LIMIT 512000 find DIR type f size LIMIT k exec du sort
  • np.fromfile 文件大小的最大限制?

    np fromfile 是否有最大文件大小 我正在尝试读取一个 48GB 文件 其中包含大约 2 1e9 条记录 每条记录有 5 个值 当我将计数限制为 8e7 时它起作用 fromfile filename dtp int 8e7 Out
  • 使用散点数据集生成热图

    我有一组 X Y 数据点 大约 10k 很容易绘制为散点图 但我想将其表示为热图 我查看了 Matplotlib 中的示例 它们似乎都已经从热图单元格值开始生成图像 有没有一种方法可以将一堆不同的 x y 转换为热图 其中 x y 频率较高
  • 在 React 中管理用户会话的最佳方法是什么?

    我对如何在 React 中管理用户会话有疑问 例如在 MVC NET 中 您只能使用 Session 对象 例如Session test 但显然 React 无法做到这一点 我正在阅读有关使用组件状态的内容 我认为在主要组件处设置状态并使用
  • Xcode Source Kit 将不会停止使用 Swift 崩溃[重复]

    这个问题在这里已经有答案了 我需要找到一个解决方案来解决 Swift 中超级棒的 Source Kit Crashing 错误 我读过很多堆栈溢出帖子 但似乎没有人有解决方案 如果有一行代码导致了问题 我不可能通过 50 多个源文件来找到它
  • 如何将字符串值从一个视图控制器传递到另一个视图控制器

    你好 我是目标 c 的新手 我有一个带有 h m xib 文件的登录视图控制器 成功登录后我需要转到第二页 场景是这样的 我正在访问网络服务 为了验证用户身份 我将用户名和密码发送到 Web 服务 作为回报我得到一个字符串值 根据字符串值的
  • 测量协议中的UserId、CID

    测量协议 为了识别新用户与回访用户 我们可以使用用户 ID 字段吗 即我们可以对用户名或其他用户唯一的标识符进行哈希处理 并将其与特定用户相关联 这样我们就可以有效地识别新用户与回访用户 关于 CID 的问题 CID 用于唯一标识用户的会话
  • EF6 与 Entity Framework Core:插入实体而不将主键(身份)重置为零

    EF6 插入已经具有主键值的实体可以正常工作 并向主键分配新值 EF Core 它尝试插入主键的值 但显然失败了异常 当 IDENTITY INSERT 设置为 OFF 时 无法在表 Asset 中插入标识列的显式值 我发现的解决方法是将
  • 如果没有 h3 标签,JQuery 手风琴将无法工作

    我正在尝试用 JQuery 制作手风琴 但遇到了一些麻烦 JQuery 网站显示如何创建您的手风琴内容 如下所示 div a href First header a div First content div a href Second h
  • 如何将数据访问映射到实体框架中的业务逻辑对象

    我在 ASP NET C MVC 应用程序中使用实体框架 我在数据访问层中有由 EF 生成的对象 namespace Project1 DataAccess using System using System Collections Gen