多态性:ORM 实体是领域实体还是数据实体?

2024-05-04

我有一个 BankAccount 表。 LINQ to SQL 生成一个名为“BankAccount”的类,如下所示。

[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.BankAccount")]
public partial class BankAccount : INotifyPropertyChanging, INotifyPropertyChanged

现在,作为一个新手,我自己新创建域对象。请参阅IBankAccount接口和FixedBankAccount类。关键点是存在多态行为 - IBankAccount 可以是固定银行帐户或储蓄银行帐户。

对于此示例的不同问题,我有以下两条评论。

  1. @mouters:“你有存储库对象和域对象,这很奇怪 - 你的存储库不应该只返回域对象吗?”
  2. @SonOfPirate:“存储库应该使用工厂来根据从数据存储检索的数据创建实例。”

问题

1)我正在手动创建域实体。这是错误的做法吗?如果是错误的,LINQ to SQL 类如何处理多态性?如何将方法添加到这些类中?

2)存储库应如何使用工厂来根据从数据存储检索的数据创建实例?有代码示例或参考吗?

3)它是否满足单一职责原则?

CODE

public interface IBankAccount
{
    int BankAccountID { get; set; }
    double Balance { get; set; }
    string AccountStatus { get; set; }
    void FreezeAccount();
    void AddInterest();
}

public class FixedBankAccount : IBankAccount
{

    public int BankAccountID { get; set; }
    public string AccountStatus { get; set; }
    public double Balance { get; set; }

    public void FreezeAccount()
    {
        AccountStatus = "Frozen";
    }

}   


public class BankAccountService
{
    RepositoryLayer.IRepository<RepositoryLayer.BankAccount> accountRepository;
    ApplicationServiceForBank.IBankAccountFactory bankFactory;

    public BankAccountService(RepositoryLayer.IRepository<RepositoryLayer.BankAccount> repo, IBankAccountFactory bankFact)
    {
        accountRepository = repo;
        bankFactory = bankFact;
    }

    public void FreezeAllAccountsForUser(int userId)
    {
        IEnumerable<RepositoryLayer.BankAccount> accountsForUser = accountRepository.FindAll(p => p.BankUser.UserID == userId);
        foreach (RepositoryLayer.BankAccount oneOfRepositoryAccounts in accountsForUser)
        {
            DomainObjectsForBank.IBankAccount domainBankAccountObj = bankFactory.CreateAccount(oneOfRepositoryAccounts);
            if (domainBankAccountObj != null)
            {
                domainBankAccountObj.BankAccountID = oneOfRepositoryAccounts.BankAccountID;
                domainBankAccountObj.FreezeAccount();

                this.accountRepository.UpdateChangesByAttach(oneOfRepositoryAccounts);
                oneOfRepositoryAccounts.Status = domainBankAccountObj.AccountStatus;
                this.accountRepository.SubmitChanges();
            }

        }
    }



}


public interface IBankAccountFactory
{
    DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositoryAccount);
}


public class MySimpleBankAccountFactory : IBankAccountFactory
{
    //Is it correct to accept repositry inside factory?
    public DomainObjectsForBank.IBankAccount CreateAccount(RepositoryLayer.BankAccount repositoryAccount)
    {
        DomainObjectsForBank.IBankAccount acc = null;

        if (String.Equals(repositoryAccount.AccountType, "Fixed"))
        {
            acc = new DomainObjectsForBank.FixedBankAccount();
        }

        if (String.Equals(repositoryAccount.AccountType, "Savings"))
        {
            //acc = new DomainObjectsForBank.SavingsBankAccount();
        }

        return acc;
    }
}

READING:

  1. 在 Linq to SQL 中设置外键 https://stackoverflow.com/questions/479791/setting-foreign-keys-in-linq-to-sql

  2. LINQ to SQL 中的多态关联 https://stackoverflow.com/questions/511092/polymorphic-associations-in-linq-to-sql

  3. DTO (linq2sql) 和 Class 对象之间的混淆! https://stackoverflow.com/questions/1323070/confusion-between-dtos-linq2sql-and-class-objects

  4. LINQ 到 XYZ 多态性? https://stackoverflow.com/questions/4467074/linq-to-xyz-polymorphism


  1. 我不完全确定您对 LINQ to SQL 的要求是什么,但手动创建域对象肯定不是错误的方法。如果您依赖于代码生成,您将无法获得正确封装的域对象。
  2. 您对工厂模式感到困惑。正如 mouters 所指出的,你有两个代表同一事物的对象:

    存储层.银行账户

    DomainObjectsForBank.IBankAccount

仅当需要“策略”来创建对象时才需要工厂。使用它们的一个经典案例是多态性和继承。您的帐户类有子类,因此有一个 AccountFactory 的情况。但是,如果情况过于复杂,则可以让存储库返回某种帐户数据对象,然后将其传递给工厂以将其转换为正确的子类域对象。相反,存储库应该从数据库获取数据,将其传递给工厂,然后从工厂返回创建的域对象。例如:

public class AccountRepository : IAccountRepository
{
    public Account GetById(Guid id)
    {
        using (AccountContext ctx = new AccountContext())
        {
            var data = (from a in ctx.Accounts
                               where a.AccountId == id
                               select new { AccountId = a.AccountId, CustomerId = a.CustomerId, Balance = a.Balance, AccountType = (AccountType)a.AccountTypeId }).First();


            return _accountFactory.Create(data.AccountId, data.CustomerId, data.Balance, data.AccountType);
        }
    }

}

UPDATE:

我对 LINQ to SQL 的建议是:

  1. 如果可以的话,请迁移到实体框架,因为它更先进并且现在得到了更好的支持。
  2. 不要使用它生成的对象作为您的域对象。如果您查看上面的代码,我会从 ctx.Accounts 查询数据并使用它来实例化我的域对象。根据我的经验,尝试使用 ORM 构建域对象是有问题的:请参阅具有行为和 ORM 的丰富域模型 https://stackoverflow.com/questions/11222720/rich-domain-model-with-behaviours-and-orm/11224734#11224734
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多态性:ORM 实体是领域实体还是数据实体? 的相关文章

  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 如何获取 EF 中与组合(键/值)列表匹配的记录?

    我有一个数据库表 其中包含每个用户 年份组合的记录 如何使用 EF 和用户 ID 年份组合列表从数据库获取数据 组合示例 UserId Year 1 2015 1 2016 1 2018 12 2016 12 2019 3 2015 91
  • WcfSvcHost 的跨域异常

    对于另一个跨域问题 我深表歉意 我一整天都在与这个问题作斗争 现在已经到了沸腾的地步 我有一个 Silverlight 应用程序项目 SLApp1 一个用于托管 Silverlight SLApp1 Web 的 Web 项目和 WCF 项目
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • VB.NET 中的静态方法实现

    我很困惑Static在 VB NET 中的实现 在 C 中 我们可以创建静态类和静态方法来为我们的应用程序编写实用方法 现在 VB NET 让我们创建Module代替静态类 如果我们在模块中创建一个方法 默认情况下它会变成静态的 但在我的应
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • 引用的程序集自动由 Visual Studio 替换

    我有 2 个项目 一个可移植类库和一个常规单元测试项目 在可移植类库中 我使用 NuGet 来引用 Microsoft BCL 可移植包 它附带 2 个程序集 System Threading Tasks dll and System Ru
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • 为什么 std::uint32_t 与 uint32_t 不同?

    我对 C 有点陌生 我有一个编码作业 很多文件已经完成 但我注意到 VS2012 似乎有以下语句的问题 typedef std uint32 t identifier 不过 似乎将其更改为 typedef uint32 t identifi
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐

  • 使用 spacy.matcher.matcher.Matcher.add() 方法的问题

    我在尝试使用 spacy 时遇到错误matcher Anaconda3 lib site packages spacy matcher matcher pyx in spacy matcher matcher Matcher add Typ
  • python 使用 shapefile 掩码 netcdf 数据

    我正在使用以下软件包 import pandas as pd import numpy as np import xarray as xr import geopandas as gpd 我有以下存储数据的对象 print precip d
  • 在 Python、Django 中下载的文件始终为空

    我在 Django 中使用以下视图来创建文件并使浏览器下载它 def aux pizarra request myfile StringIO StringIO myfile write hello response HttpResponse
  • SignalR 无法连接到 SSL 上的 Azure Redis

    我目前在 Azure 上托管我的 redis 缓存服务器 并让 signalR 依赖它作为骨干 使用以下内容 GlobalHost DependencyResolver UseRedis 服务器 端口 密码 eventKey 这可以在端口
  • 如何禁止在应用程序启动时创建空日志文件?

    我已经在我的应用程序中成功配置了 log4net 但有一件事对我来说有点烦人 即使没有发生错误 日志文件也会在我的应用程序启动后创建 空 我想仅在出现错误后才创建日志文件 我实际上在这个线程中找到了一种方法来做到这一点 http www l
  • rpart 绘图文本较短

    我正在使用prp函数从rpart plot包来绘制一棵树 对于像状态这样的分类数据 它给出了一个非常长的变量列表 并且使其可读性较差 如果超过一定长度 有什么方法可以将文本换行为两行或更多行吗 这是一个将长分割标签包装在多个标签上的示例 线
  • 更新通过 JungleDisk 上传的 Amazon S3 文件的权限

    我开始使用 Jungle Disk 将文件上传到与 Cloudfront 发行版相对应的 Amazon S3 存储桶 即我可以通过 http URL 访问它 并且我使用 Amazon 作为 CDN 我面临的问题是 Jungle Disk 没
  • 快速NLTK解析成语法树

    我正在尝试将数百个句子解析为语法树 我需要快速完成 问题是如果我使用 NLTK 那么我需要定义一个语法 而我不知道我只知道它会是英语 我尝试使用this https github com emilmont pyStatParser统计解析器
  • Visual Studio 中的 C 编程

    我可以使用 Visual Studio 来学习 C 编程吗 在新项目菜单中 我可以在 Visual Basic Visual C Visual C Visual F 等之间进行选择 但我没有看到 C 或 Visual C 简短回答 是的 您
  • IE 抛出 JavaScript TypeError 但在 chrome 上不抛出

    描述在我们的 Magento 购物车上 当用户单击添加到购物篮在任何 Internet Explorer 浏览器的 产品详细信息 页面上单击按钮 浏览器中都会弹出一个包含以下错误消息的窗口 异常 类型错误 无法获取未定义或空引用的属性 ta
  • 使用 Java 8 Stream 的构建器模式

    我正在用一个简单的循环构建一个对象 WebTarget target getClient target u for Entry
  • 调用不同 SELECT 语句的 MySQL IF/CASE 语法

    我在使用 MySQL 时遇到问题IF or CASE syntax 程序是这样的 我有一个调用 MySQL 查询的 PHP 项目 假设 PHP 传递变量X If X is not 0那么它应该执行如下查询 SELECT FROM table
  • 在 Chrome 中使用 window.open 打开本地 HTML 文件

    我想通过 Javascript 打开本地 HTML 文件 使用 window open file C Users wins Desktop exclusiveWordpress html mywindow 但它会打开一个带有空白页面的新窗口
  • 为什么这个表达式会导致浮点错误?

    所以浮点运算是inexact http en wikipedia org wiki Floating point但这并不能完全解释这里发生的事情 46 pry main gt a 0 05 gt 0 05 47 pry main gt a
  • R中向后历史搜索

    通常在我的机器中 我可以通过键入我想要向后搜索的命令的所需第一个字符来向后搜索 R 的历史记录 然后使用 PageUp 或 PageDown 键浏览 R 历史记录中的所有条目 我现在在远程集群中以访客身份工作 此选项在本机上不可用 有谁知道
  • Swift - 如何 popViewController 动画两个视图回来

    我的故事板里有一些UIViewControllers和我的主要UINavigationController 然后我有一个 UIViewControllertableView didSelectRowAtIndexPath我弹出UIViewC
  • Redshift Serverless 上的关系 stl_load_errors 权限被拒绝

    我使用 Amazon Redshift Serverless 和查询编辑器 v2 但在用户权限方面遇到问题 在S3中导入数据 csv 时出现以下错误 ERROR Load into table x failed Check sys load
  • SQL 数据范围最小值最大值类别

    我想确定 2 个类别的范围 A 类和 B 类 A 从 1 到 15 开始 B 从 16 到 31 开始 然后 A 再次从 32 到 40 开始 现在如果运行此查询 select min range max range from table
  • 如何将 nlsList 中的系数获取到数据帧中?

    有没有办法只从 nlsList 中提取估计值 样本数据 library nlme dat lt read table text time gluc starch solka 1 6 32 7 51 1 95 2 20 11 25 49 6
  • 多态性:ORM 实体是领域实体还是数据实体?

    我有一个 BankAccount 表 LINQ to SQL 生成一个名为 BankAccount 的类 如下所示 global System Data Linq Mapping TableAttribute Name dbo BankAc