0

BankAccount テーブルがあります。LINQ to SQL は、以下に示すように「BankAccount」という名前のクラスを生成します。

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

今、初心者なので、自分でドメイン オブジェクトを新しく作成しています。IBankAccount インターフェイスと FixedBankAccount クラスを参照してください。重要なポイントは、ポリモーフィックな動作があることです。IBankAccount は、FixedBankAccount または SavingsBankAccount にすることができます。

この例の別の質問については、次の 2 つのコメントがあります。

  1. @mouters : 「リポジトリ オブジェクトとドメイン オブジェクトがあるのは奇妙です。リポジトリはドメイン オブジェクトを返すだけではいけませんか?」</li>
  2. @SonOfPirate : 「ファクトリは、データ ストアから取得したデータに基づいてインスタンスを作成するためにリポジトリで使用する必要があります。」</li>

質問

1) ドメイン エンティティを手動で作成しています。間違ったアプローチですか?それが間違っている場合、LINQ to SQL クラスはポリモーフィズムをどのように処理しますか? これらのクラスにメソッドを追加する方法は?

2) データ ストアから取得したデータに基づいてインスタンスを作成するために、リポジトリでファクトリをどのように使用する必要がありますか? コード例またはリファレンスはありますか?

3) 単一責任原則を満たすか?

コード

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

読書:

  1. Linq の外部キーを SQL に設定する

  2. LINQ to SQL でのポリモーフィックな関連付け

  3. DTO (linq2sql) と Class オブジェクトの間の混乱!

  4. LINQ から XYZ へのポリモーフィズム?

4

1 に答える 1

1
  1. LINQ to SQL に関してあなたが何を求めているのか完全にはわかりませんが、ドメイン オブジェクトを手動で作成するアプローチが間違っているわけではありません。コード生成に依存している場合、適切にカプセル化されたドメイン オブジェクトを取得できません。
  2. 工場のパターンに関して混乱しています。mouters が指摘したように、同じものを表す 2 つのオブジェクトがあります。

    RepositoryLayer.BankAccount

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

}

更新

LINQ to SQL に関する私のアドバイスは次のとおりです。

  1. より高度で、より適切にサポートされているため、可能であれば Entity Framework に移動してください。
  2. 生成されたオブジェクトをドメイン オブジェクトとして使用しないでください。上記のコードを見ると、ctx.Accounts からデータをクエリし、それを使用してドメイン オブジェクトをインスタンス化しています。私の経験では、ORM を使用してドメイン オブジェクトを構築しようとすると問題が発生します。動作と ORM を使用したリッチ ドメイン モデルを参照してください。
于 2012-06-29T09:07:06.840 に答える