EFとDDDを使用して単純なアプリケーションをセットアップするために数日を費やした後、私は非常にイライラしていると言わなければなりません。Linq-to-SQLを使用したほうがいいと思い、DDDとEFのことをすべて忘れてしまいます。
EF付き
a)適切な読み取り専用コレクションを作成することはできません
b)子アイテムのコレクションから何かを削除すると、1つ以上の外部キープロパティがnull不可のメッセージであるため、関係を変更できなかったことがよくあります。
c)親のすべての子アイテムを削除して再挿入する簡単な方法はありません。
私が見つけた回避策がかなり厄介に見えることを考えると、これらはすべて私にとってほとんどショーストッパーです。誰かがこれらの問題に対処する簡単なリポジトリをまとめることができましたか?
はいの場合、コードを共有していただけませんか?!?
また、これが大きなトピックであることを私は知っていますが、大規模なWebアプリケーションで実際のDDDの利点を実際に体験した人はいますか?私たちは皆理論を知っていますが、それが実際に面倒な価値があるかどうかについてのアイデアを持っているといいでしょう!
さて、これまでのところ、あらゆる種類の厄介な回避策を実行することなく実行できる最善の方法は、何かをクエリするときにAsNoTracking()を使用することです。そうすれば、私は自分の情報を入手し、EFは私の背後で何もしなくても一人で去ります。コレクションから削除できるようになり、削除もできるようになりました(idはこれからsqlに戻らなければならないと誰が思うでしょう!)AsNoTrackingを使用する際の落とし穴を知っている人はいますか?オブジェクトに基づいてSQLを生成し、それらにデータを入力したり、更新/削除したりできる限り、問題はありません。とにかく追跡全体が行き過ぎですか?
namespace EShop.Models.Repositories
{
public class CustomerRepository : BaseRepository, IRepository<Customer, Int32>
{
public CustomerRepository() : base(new EShopData()) { }
#region CoreMethods
public void InsertOrUpdate(Customer customer)
{
if (customer.CustomerId > 0)
{
// you cannot use remove, if you do you ll attach and then you ll have issues with the address/cards below
// dbContext.Entry<CustomerAddress>(address).State = EntityState.Added; will fail
dbContext.Database.ExecuteSqlCommand("DELETE FROM CustomerAddress WHERE CustomerId = @CustomerId", new SqlParameter("CustomerId", customer.CustomerId));
dbContext.Database.ExecuteSqlCommand("DELETE FROM CreditCard WHERE CustomerId = @CustomerId", new SqlParameter("CustomerId", customer.CustomerId));
foreach (var address in customer.Addresses)
dbContext.Entry<CustomerAddress>(address).State = EntityState.Added;
foreach (var card in customer.CreditCards)
dbContext.Entry<CreditCard>(card).State = EntityState.Added;
dbContext.Entry<Customer>(customer).State = EntityState.Modified;
}
else
{
dbContext.Entry<Customer>(customer).State = EntityState.Added;
foreach (var card in customer.CreditCards)
dbContext.Entry<CreditCard>(card).State = EntityState.Added;
foreach (var address in customer.Addresses)
dbContext.Entry<CustomerAddress>(address).State = EntityState.Added;
}
}
public void Delete(int customerId)
{
var existingCustomer = dbContext.Customers.Find(customerId);
if (existingCustomer != null)
{
//delete cards
var creditCards = dbContext.CreditCards.Where(c => c.CustomerId == customerId);
foreach (var card in creditCards)
dbContext.Entry<CreditCard>(card).State = EntityState.Deleted;
//delete addresses
var addresses = dbContext.CustomerAddresses.Where(c => c.CustomerId == customerId);
foreach (var address in addresses)
dbContext.Entry<CustomerAddress>(address).State = EntityState.Deleted;
//delete basket
dbContext.Entry<Customer>(existingCustomer).State = EntityState.Deleted;
}
}
public Customer GetById(int customerId)
{
return dbContext.Customers.Include("Addresses").AsNoTracking().SingleOrDefault(c => c.CustomerId == customerId);
}
public IList<Customer> GetPagedAndSorted(int pageNumber, int pageSize, string sortBy, SortDirection sortDirection)
{
return null;
}
public void Save()
{
dbContext.SaveChanges();
}
#endregion CoreMethods
#region AdditionalMethods
#endregion AdditionalMethods
}
}