Reputation: 22652
I have a BankAccount table. LINQ to SQL generates a class named “BankAccount” as shown below.
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.BankAccount")]
public partial class BankAccount : INotifyPropertyChanging, INotifyPropertyChanged
Now, being a newbie, I am newly creating the domain objects myself. Please see IBankAccount interface and FixedBankAccount class. The key point is there is polymorphic behavior – the IBankAccount can be FixedBankAccount or SavingsBankAccount.
For a different question with this example, I have following two comments.
QUESTIONS
1) I am manually creating domain entities. Is it wrong approach? If it is wrong, how the LINQ to SQL classes handle the polymorphism? How to add the methods to those classes?
2) How the factory should be used by the repository to create the instance based on the data retrieved from the data store? Any code example or reference ?
3) Will it satisfy Single Responsibility Principle?
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:
Upvotes: 1
Views: 774
Reputation: 8295
You have got yourself in a muddle regarding the factory pattern. As mouters has pointed out, you have two objects representing the same thing:
RepositoryLayer.BankAccount
DomainObjectsForBank.IBankAccount
Factories are only required when a 'strategy' is required for object creation. A classic case for their use is polymorphism & inheritance. Your account class has sub classes, so there is a case for an AccountFactory. But where you have over complicated the situation is by having the repository return some kind of account data object, then passing this to the factory to convert it to the correct sub classed domain object. Instead, the repository should get the data from the database, pass it to the factory, and then return the created domain object from the factory. For example:
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:
My Advice regarding LINQ to SQL is:
Upvotes: 1