ASP.NET en iyi Havuz Deseni MVC
Geçenlerde ASP.NET MVC (seviyorum) öğrendim. Bağımlılık enjeksiyon her istek Depoyu bir örneği yüklemek için kullanan bir şirket için çalışıyorum, ve bu depoyu kullanarak aşinayım.
Ama şimdi benim kendi MVC uygulamaları birkaç yazıyorum. Tam benim şirket kullanır deposunu nasıl ve neden anlamıyorum, ve veri erişim uygulamak için en iyi yaklaşım karar vermeye çalışıyorum.
C kullanıyorum# ve Varlık Çerçevesi (tüm son sürümleri ile).
Veri erişim kullanım için üç genel yaklaşım görüyorum.
Düzenli DB kullanarak bir deyimi her zaman içinde ben access veri içeriği. Bu basit ve iyi çalışıyor. Eğer iki yer bir istek içinde aynı veri okumak gerekir, ancak veri iki kez okunmalıdır. (İstek başına tek bir depo ile, aynı örneği her iki yerde kullanılacak ve ikinci okuma sadece ilk okuma verileri geri döneceğini anlıyorum.)
Tipik repository pattern. Anlayamadığım nedenlerden dolayı, bu tipik desen her tablo veritabanından kullanılan kapsayıcı bir sınıf oluşturulmasıdır. Bu bana yanlış geliyor. Ayrıca arabirimleri olarak uygulandığından beri aslında, teknik olarak her iki tablo için sarıcı sınıflar oluşturmak olurdum. EF benim için tablolar oluşturur. Bu yaklaşım mantıklı inanmıyorum.
Ayrıca depo tek bir sınıf tüm varlık nesneleri hizmet etmek için yaratılmış olduğu generic repository pattern var. Bu bana çok daha mantıklı geliyor. Ama diğerleri için mantıklı mı? En iyi yaklaşım, yukarıda bağlantısı nedir?
Bu konuda diğerlerinden de bir katkım olsun isterim. Kendi depo yazarken, yukarıda bunlardan birini kullanarak bunu yapıyor, ya da tamamen farklı bir şey. Lütfen paylaşın.
CEVAP
#2 karışımı ve #3, ama mümkünse katı genel bir depo tercih ederim (hatta #3 bağlantı için önerilen daha sıkı) kullandım. Kötü birim testi ile oynadığı için iyi değil #1.
Eğer daha küçük bir etki alanı veya ihtiyaç daraltmak hangi varlıkları etki sağlar için sorgulanan, sanırım #2 veya #3 Bu tanımlar, işletmenin belirli bir depo arabirimleri kendilerini uygulamak genel depo - mantıklı. Ancak, bu çok yorucu ve gereksiz bir arayüz ve sorgulamak istiyorum her varlık için somut bir uygulama yazmak için bulabilirsiniz. Ne iyi gelir public interface IFooRepository : IRepository<Foo>
(izin verilen toplam kökleri bir dizi geliştiriciler kısıtlamak gerekiyor tabii yine)?
Ben sadece tanımlamak benim genel depo arayüzü ile Add
, Remove
, Get
, GetDeferred
, Count
, ve Find
yöntem (Bul döndürür IQueryable
arayüz sağlayan SERİ), oluşturma bir beton genel uygulama ve çağrı onu bir gün. Ağır Find
güveniyor ve böylece ETMENİZ. Eğer belirli bir sorgu birden çok kez kullanmak gerekiyorsa, uzatma yöntemlerini kullanmak ve sorgu ETMENİZ kullanarak yazma.
Bu kalıcılık benim ihtiyacının •'ini kapsar. EÄŸer genel yapılamayacak kalıcılık eylem bir tür gerçekleÅŸtirmek için ihtiyacım olursa, yerli ICommand
bir API kullanıyorum. Örneğin, benim etki alanı parçası olarak karmaşık bir sorgu yapmak istiyorum, ya da belki de toplu bir komut yapmak istiyorum Arabiriminin ile çalışıyorum demek. API kabaca şöyle görünür:
// marker interface, mainly used as a generic constraint
public interface ICommand
{
}
// commands that return no result, or a non-query
public interface ICommandNoResult : ICommand
{
void Execute();
}
// commands that return a result, either a scalar value or record set
public interface ICommandWithResult<TResult> : ICommand
{
TResult Execute();
}
// a query command that executes a record set and returns the resulting entities as an enumeration.
public interface IQuery<TEntity> : ICommandWithResult<IEnumerable<TEntity>>
{
int Count();
}
// used to create commands at runtime, looking up registered commands in an IoC container or service locator
public interface ICommandFactory
{
TCommand Create<TCommand>() where TCommand : ICommand;
}
Şimdi özel bir komut göstermek için bir arayüz oluşturabilirsiniz.
public interface IAccountsWithBalanceQuery : IQuery<AccountWithBalance>
{
Decimal MinimumBalance { get; set; }
}
Somut bir uygulama oluşturmak ve ham SQL, Arabiriminin HQL, ne olursa olsun kullanmak ve servis Bulucu ile kayıt olabilirim.
Şimdi iş benim mantık böyle bir şey yapabilirim:
var query = factory.Create<IAccountsWithBalanceQuery>();
query.MinimumBalance = 100.0;
var overdueAccounts = query.Execute();
Ayrıca bir Şartname desenli IQuery
inşa anlamlı, kullanıcı giriş-tahrik sorguları, yerine sahip bir arayüz ile bir milyon kafa karıştırıcı özellikleri, ama varsayar değilsin bulmak belirtimi desen kafa karıştırıcı kendi doğru ;).
Bulmacanın son parçası deponuzu belirli yapmanız gerektiğinde, iş öncesi ve sonrası depo operasyon. Şimdi, sen-ebilmek kolayca yaratmak bir uygulaması genel depo için belirli bir varlık, o zaman geçersiz kılma ilgili yöntem(ler) ve yapman gerekeni yap ve update IoC veya servis Bulucu kaydı ve bu son.
Ancak, bazen bu mantık çapraz-kesim ve depo garip bir yöntem geçersiz kılma uygulamaktır. Temelde bir olay havuzu olan IRepositoryBehavior
, yarattım. Sadece kafamın üst kapalı kaba bir tanım altında)
public interface IRepositoryBehavior
{
void OnAdding(CancellableBehaviorContext context);
void OnAdd(BehaviorContext context);
void OnGetting(CancellableBehaviorContext context);
void OnGet(BehaviorContext context);
void OnRemoving(CancellableBehaviorContext context);
void OnRemove(BehaviorContext context);
void OnFinding(CancellableBehaviorContext context);
void OnFind(BehaviorContext context);
bool AppliesToEntityType(Type entityType);
}
Şimdi, bu davranışlar herhangi bir şey olabilir. Denetim, güvenlik denetimi, yumuşak silin, etki alanı kısıtlamaları, doğrulama, vb zorlanarak. Ben oluşturmak bir davranış, kayıt ile IoC veya hizmeti veren firma ve değiştirmek benim genel depo için bir koleksiyon kayıtlı IRepositoryBehavior
s ve kontrol her davranış karşı mevcut depo türü ve şal operasyon öncesi/sonrası işleyicileri için her uygun davranış.
İşte bir örnek, yumuşak davranış, delete (yumuşak silme anlamına geldiğini ne zaman birisi sorar silmek için bir varlık, biz sadece işareti olarak silinmiş olamaz döndü tekrar, ama asla fiziksel olarak kaldırıldı).
public SoftDeleteBehavior : IRepositoryBehavior
{
// omitted
public bool AppliesToEntityType(Type entityType)
{
// check to see if type supports soft deleting
return true;
}
public void OnRemoving(CancellableBehaviorContext context)
{
var entity = context.Entity as ISoftDeletable;
entity.Deleted = true; // when the NHibernate session is flushed, the Deleted column will be updated
context.Cancel = true; // set this to true to make sure the repository doesn't physically delete the entity.
}
}
Evet, bu temelde Arabiriminin olay dinleyicileri daha basit ve soyutlanmış bir uygulama olduğunu, ama bu yüzden seviyorum. A) ben birim test bir davranış olmadan getirerek Arabiriminin içine resim B) kullanabilirim bu davranışlar dışında Arabiriminin (ki deposudur istemci uygulaması bu sarar DİNLENME hizmeti çağrıları) C) NH olay dinleyicileri olabilir gerçek bir dert ;)
Yerel depo ÅŸube sadece uzaktan havuz B...
Statik sınıf ve singleton deseni arası...
Java singleton deseni uygulamak için e...
C Singleton tasarım deseni...
Builder Tasarım deseni ve Fabrika Tasa...