6

Yeni bir hizmet eklemek istediğimde UoW koduna dokunmaya gerek duymama neden olacak şekilde, iş birimimi hizmetlerimden veya havuzumdan ayırmaya çalışıyorum. Bunu nasıl yaparım? Hizmetlerden veya repodan çalışma birleştirme birimi

_categoryService = _unitOfWork.Get<ICategoryService>(); 

bunun yerine sadece söyleyebiliriz

_unitOfWork.CategoryService.Add(category) 

arasında

;

_categoryService.Add(category); 
+0

Senaryonuz hakkında daha fazla bilgi verebilir misiniz? Bana bağımlılık enjeksiyonundan bahsediyorsunuz (kodunuz ICategoryService'ye bağlıdır ve otomatik olarak enjekte etmek istersiniz), fakat sorunuzdan belli değildir. –

+0

Merhaba! UoW modelini incelemek için bir MVC4 test projem var. Bir denetleyicim, depoya başvuran bir hizmet sınıfım var. Ama gördüğünüz gibi UoW'mda bir Category olarak bu Kategori Hizmetim var. Sonra, gelecekte bir şey için yeni bir hizmet oluşturduğumda, bu hizmeti sahip olduğum UoW sınıfına eklemem gerektiğini anladım.Sadece hangi arabirime geçtiğime bağlı olarak bir hizmet türü döndüren Get işlevine sahip olmanın bir yolunu bulmaya çalışıyorum. Bunun bunun için doğru yol olup olmadığından emin değilim. Teşekkürler! –

+0

UoW kabı için ne kullanıyorsunuz? Bazı IoC'leri kullanmalı, güzel bir liste için bu sayfayı kontrol etmelisiniz: http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx Çoğu, () yöntemini veya benzerini çözer ve bunları asp.net mvc'de varsayılan bağımlılık çözümleyici olarak kullanırsınız, böylece denetleyicinize sadece IService parametresini eklersiniz. Bu ne soruyorsun? –

cevap

15

ben yeni servisi

eklemek istedikleri zaman UOW kodu dokunmak zorunda kalmazsınız böylece benim hizmetler veya deposundan işin Birimimi ayrıştırmak çalışıyorum

Eh, bu iyi bir başlangıç! ;-)

Sunmakta olduğum çözüm tek ve olası çözüm değil, UoW'yi uygulamak için birkaç iyi yol var (Google size yardımcı olacak). Ama bu sana büyük resmi vermeli. IUnitOfWork ve IRepository

public interface IUnitOfWork : System.IDisposable 
{ 
    IRepository<TEntity> GetRepository<TEntity>() where TEntity : class; 
    void Save(); 
} 

public interface IRepository<T> : IDisposable where T : class 
{ 
    void Add(T entity); 
    void Delete(T entity); 
    void Update(T entity); 
    T GetById(long Id); 
    IEnumerable<T> All(); 
    IEnumerable<T> AllReadOnly(); 
    IEnumerable<T> Find(Expression<Func<T, bool>> predicate); 
} 

uygulamaları oldukça basittir (ı okunabilirliği amacıyla tüm yorumlarımı kaldırdık, ancak ;-) sizindir eklemeyi unutmayın)

public class UnitOfWork<TContext> : IUnitOfWork where TContext : IDbContext, new() 
{ 
    private readonly IDbContext _ctx; 
    private Dictionary<Type, object> _repositories; 
    private bool _disposed; 

    public UnitOfWork() 
    { 
    _ctx   = new TContext(); 
    _repositories = new Dictionary<Type, object>(); 
    _disposed  = false; 
    } 

    public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class 
    { 
    if (_repositories.Keys.Contains(typeof(TEntity))) 
     return _repositories[typeof(TEntity)] as IRepository<TEntity>; 

    var repository = new Repository<TEntity>(_ctx); 
    _repositories.Add(typeof(TEntity), repository); 
    return repository; 
    } 

    public void Save() 
    { 
    try 
    { 
     _ctx.SaveChanges(); 
    } 
    catch (DbUpdateConcurrencyException ex) 
    { 
     ex.Entries.First().Reload(); 
    } 
    } 

    … 
} 

public class Repository<T> : IRepository<T> where T : class 
{ 
    private readonly IDbContext _context; 
    private readonly IDbSet<T> _dbset; 

    public Repository(IDbContext context) 
    { 
    _context = context; 
    _dbset = context.Set<T>(); 
    } 

    public virtual void Add(T entity) 
    { 
    _dbset.Add(entity); 
    } 

    public virtual void Delete(T entity) 
    { 
    var entry = _context.Entry(entity); 
    entry.State = EntityState.Deleted; 
    } 

    public virtual void Update(T entity) 
    { 
    var entry = _context.Entry(entity); 
    _dbset.Attach(entity); 
    entry.State = EntityState.Modified; 
    } 

    public virtual T GetById(long id) 
    { 
    return _dbset.Find(id); 
    } 

    public virtual IEnumerable<T> All() 
    { 
    return _dbset.ToList(); 
    } 

    public virtual IEnumerable<T> AllReadOnly() 
    { 
    return _dbset.AsNoTracking().ToList(); 
    } 

    public IEnumerable<T> Find(Expression<Func<T, bool>> predicate) 
    { 
    return _dbset.Where(predicate); 
    } 

} 
:

Öncelikle 2 arayüzleri yaratmak

Gördüğünüz gibi, her iki uygulama da IDbContext arabirimini kullanır.

public interface IDbContext 
{ 
    DbSet<T> Set<T>() where T : class; 
    DbEntityEntry<T> Entry<T>(T entity) where T : class; 
    int SaveChanges(); 
    void Dispose(); 
} 

(Gördüğünüz gibi, ben kullanıyorum EntityFramework Kod İlk) Şimdi bütün sıhhi tesisat şekilde ayarlandığını

, aşağıdakiler bu bir göz atalım: Bu arayüz sadece kolay test amaçlıdır bir serviste kullanılabilir. Şöyle bir baz hizmeti:

internal class Service<T> where T : class 
{ 
    internal Service(Infrastructure.IUnitOfWork uow) 
    { 
    _repository = uow.GetRepository<T>(); 
    } 

    protected Infrastructure.IRepository<T> Repository 
    { 
    get { return _repository; } 
    } 

    private readonly Infrastructure.IRepository<T> _repository; 
} 

Ve tüm hizmetlerim bu taban hizmetinden devralır.

internal class CustomerService : Service<Model.Customer> 
{ 
    internal CustomerService(Infrastructure.IUnitOfWork uow) : base(uow) 
    { 
    } 

    internal void Add(Model.Customer customer) 
    { 
    Repository.Add(customer); 
    } 

    internal Model.Customer GetByID(int id) 
    { 
    return Repository.Find(c => c.CustomerId == id); 
    } 

} 

Ve işte bu! Eğer bir cephe yöntemiyle veya başka bir yere de birkaç hizmetlerine aynı UOW paylaşmak istiyorsanız

Şimdi, sadece bu gibi görünebilir:

using (var uow = new UnitOfWork<CompanyContext>()) 
{ 
    var catService = new Services.CategoryService(uow); 
    var custService = new Services.CustomerService(uow); 

    var cat = new Model.Category { Name = catName }; 
    catService.Add(dep); 

    custService.Add(new Model.Customer { Name = custName, Category = cat }); 

    uow.Save(); 
} 

Umut bu yardımcı olur!

+0

Üzgünüz, uzun bir tatilden yeni döndüm. Bunu deneyeceğim. Çok teşekkürler! –

+0

Max, sana bir soru sormama izin ver. Depo yöntemlerini sanal olarak tanımladınız, böylece bunları geçersiz kılabilirsiniz. Deponun içinden gelen herhangi bir sınıfınız yoksa (özellikle belirli bir şekilde silmek için bir depo istiyorum) bunları geçersiz kılabilirsiniz. Uzatma yöntemleri fikrini sevmiyorum ama bir çıkış yolu. Deposu (örn. CustomerRepository) gelen ve bazı yöntemleri geçersiz kılmak ve uzantı yöntemlerine gerek kalmadan yenilerini eklemek sınıfları ile çalışmak için bir yol olur mu? – snekkke

+0

@snekkke Geri bildiriminiz için teşekkür ederiz. Aslında haklısın. Sanal burada oldukça işe yaramaz. Bir şeyi kişiselleştirmenin bir yolu, "hizmetlerinize" özel yöntemler eklemek olabilir. 'Iç Model.Customer GetByExternalIdAndChannelAsReadOnly (string externalCode, KanalNo kanalı) { var müşter = Repository.Find (c => c.ExternalCode == externalCode && c.ChannelId == (byte: yöntemlerin bu tür ekleme iş yapabilirdi) kanalı) .SingleOrDefault(); dönüş cust; } ' – MaxSC

İlgili konular