我有一个 BankAccount 表。 LINQ to SQL 生成一个名为“BankAccount”的类,如下所示。
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.BankAccount")]
public partial class BankAccount : INotifyPropertyChanging, INotifyPropertyChanged
现在,作为一个新手,我自己新创建域对象。请参阅IBankAccount接口和FixedBankAccount类。关键点是存在多态行为 - IBankAccount 可以是固定银行帐户或储蓄银行帐户。
对于此示例的不同问题,我有以下两条评论。
- @mouters:“你有存储库对象和域对象,这很奇怪 - 你的存储库不应该只返回域对象吗?”
- @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:
在 Linq to SQL 中设置外键 https://stackoverflow.com/questions/479791/setting-foreign-keys-in-linq-to-sql
LINQ to SQL 中的多态关联 https://stackoverflow.com/questions/511092/polymorphic-associations-in-linq-to-sql
DTO (linq2sql) 和 Class 对象之间的混淆! https://stackoverflow.com/questions/1323070/confusion-between-dtos-linq2sql-and-class-objects
LINQ 到 XYZ 多态性? https://stackoverflow.com/questions/4467074/linq-to-xyz-polymorphism
- 我不完全确定您对 LINQ to SQL 的要求是什么,但手动创建域对象肯定不是错误的方法。如果您依赖于代码生成,您将无法获得正确封装的域对象。
-
您对工厂模式感到困惑。正如 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 的建议是:
- 如果可以的话,请迁移到实体框架,因为它更先进并且现在得到了更好的支持。
- 不要使用它生成的对象作为您的域对象。如果您查看上面的代码,我会从 ctx.Accounts 查询数据并使用它来实例化我的域对象。根据我的经验,尝试使用 ORM 构建域对象是有问题的:请参阅具有行为和 ORM 的丰富域模型 https://stackoverflow.com/questions/11222720/rich-domain-model-with-behaviours-and-orm/11224734#11224734
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)