I have an entity class
public partial class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
}
and this entity
public partial class User
{
public User()
{
this.Tokens = new HashSet<Token>();
}
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Name { get; set; }
public virtual ICollection<Token> Tokens { get; set; }
}
I have a repository pattern
public abstract class DataRepositoryBase<T> : IDataRepository<T>
where T : class, new()
{
protected abstract T AddEntity(T entity);
protected abstract T UpdateEntity(T entity);
protected abstract IEnumerable<T> GetEntities();
protected abstract T GetEntity(int id);
}
How can I call repository using generic data repository using some thing like this.<T> just using generic interface not creating new class? Thanks.
_datarepositorypattern.GetDataRepository<IProductRepository>();
_datarepositorypattern.GetDataRepository<IUserRepository>();
what i want, somthing like this.
var obj = _datarepositorypattern.GetDataRepository<IDataRepository<User>>();
//then i can access use
obj.GetEntities();
update
I already created repository
this repository can return
public DataRepositoryBase<Product> ProductRepository => new ProductRepository();
in the service class
private readonly UnitOfWork _unitOfWork;
public ProductServices(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
Product[] IProductServices.GetProduct()
{
var repository = _unitOfWork.ProductRepository;
return repository.Get().ToArray();
}
i use this current repository method like this.
what i wanted create dynamic repository so i do not updating my repository again only updating my service class with code like this.
var obj = _datarepositorypattern.GetDataRepository<IProductRepository>();
obj.GetEntities();
just using repository repository pattern i can get dynamic repository product
var obj = _datarepositorypattern.GetDataRepository<IUserRepository>();
obj.GetEntities();
just using repository repository pattern i can get dynamic repository User.
UPDATE
I just googling this is an repositoryfactorypattern can anyone help me.
as you've written it here you need you need new classes. You specify the IProductRepository and IUserRepository
that means you need something like
class UserRepository : DataRepositoryBase<User>, IUserRepository
{
//userrepository code here
}
otherwise you would get something like
_datarepositorypattern.GetDataRepository<IDataRepository<User>>();
expecially since your datarepository class is abstract you need a concrete implementation somewhere
Update: example not using entity specific repositories
If you really want to avoid entity specific repositories you can look at breeze.
you still need something like theis
class MyContext : DbContext {
DbSet<Product> Products {get; set;}
DBSet<User> Users {get; set;}
}
but then you can call a context provider like this
public class DataRepositoryBase<T> : IDataRepository<T> {
readonly EFContextProvider<User> _contextProvider =
new EFContextProvider<User>();
public void SaveEntity(JObject saveBundle) {
_contextProvider.SaveChanges(saveBundle);
}
}
now you can just call new DataBaseObjectRepository() (or have that code in your GetDataRepository method)
maybe that is a place to start. You do need something like DbContext that tells you how to map different types to different tables.
Related
Im doing an MVC 5 proyect using DI with IoC (Autofac) and the use of Generic Repository for the Data access part.
Now, my controller have an interface as a property injected to it called IProg_II_ModelFactory, this is the concrete class in question:
public class Prog_II_ModelFactory : IProg_II_ModelFactory
{
#region Fields
private readonly IGenericRepository<T> _genericRepository;
#endregion
#region Ctor
public Prog_II_ModelFactory(
IGenericRepository<T> genericRepository
)
{
_genericRepository = genericRepository;
}
#endregion
#region Methods
public Prog_II_Model SetProgIIModelStartUp()
{
var model;
model.FillList = _genericRepository.GettAll();
//Other things to be filled.
return model;
}
}
And my controller is injecting the interface of this class, here is the controller:
public class HomeController : Controller
{
private readonly IProg_II_ModelFactory _prog_II_ModelFactory;
public HomeController(
IProg_II_ModelFactory prog_II_ModelFactory
)
{
_prog_II_ModelFactory = prog_II_ModelFactory;
}
public ActionResult Index()
{
var model = _prog_II_ModelFactory.SetProgIIModelStartUp();
return View(model);
}
}
The problem with this is that Prog_II_ModelFactory must be generic (Prog_II_ModelFactory<T> where T : class)
The problem with this is that, it wont stop there, then it will ask me that the controller should also be generic and on top of that as Im using Autofac, the partial class to for the binding must be generic too and the App_Start itself!.
Is there any way I can use the Generic Interface of My repository without to flow TEntity all the way to App_Start ?
I read that I can use a method? but a lot of people is against this.
Edit:
Maybe instead of the property being Out of T, I have to type it?
for example:
#region Fields
private readonly IGenericRepository<Student> _genericRepository_Student;
private readonly IGenericRepository<Teacher> _genericRepository_Teacher;
#endregion
#region Ctor
public Prog_II_ModelFactory(
IGenericRepository<Student> genericRepository_Student,
IGenericRepository<Teacher> genericRepository_Teacher
)
{
_genericRepository_Student = genericRepository_Student;
_genericRepository_Teacher = genericRepository_Teacher;
}
#endregion
This means I cant do it at runtime, I have to know to which entity at compile time, what if I have 20 tables.
Edit 2:
This is my Model:
namespace Prog_II.Models
{
public class Prog_II_Model
{
#region Fields
public StudentModel Student{ get; set; }
public List<TurnModel> Turns{ get; set; }
public List<CarrerModel> Carrers { get; set; }
public List<StudentModel> Students{ get; set; }
#endregion
#region Ctor
public Prog_II_Model(){}
#endregion
}
public class StudentModel
{
#region Fields
public string Name { get; set; }
public string LastName{ get; set; }
public string NumberId { get; set; }
public string Carrer { get; set; }
public string Turn { get; set; }
#endregion
}
public class TurnModel
{
public string Description{ get; set; }
}
public class CarrerModel
{
public string Description{ get; set; }
}
}
And sure enough I pass a Prog_II_Model in my view:
#using Prog_II.Models
#model Prog_II_Model
public HomeController(Prog_II_ModelRepository modelRepository)...
public class Prog_II_ModelRepository()
{
IGenericRepository<Student> _genericRepository_Student; // get from somewhere
public Prog_II_Model GetModel()
{
var model = new Prog_II_Model();
model.Student = _genericRepository_Student.Get(); // some student
// put the rest of data into your huge all-encompassing model
return model;
}
}
That's just the idea - if you put all your data in a single model object, type-specific repositories are useful inside this single model repo, but it itself has no need to be generic (as opposed to general :)
I think there's something wrong with this One Huge Model approach, but YMMV.
Is your HomeController supposed to handle multiple entity types (Student, Teacher, Janitor, Dog, Cat, ...)? Is your Model flexible enough to handle all and any of them? If yes, use a non-generic repository interface, returning an object or some base entity type. If no, and you have different models per entity type (Dog has Color and Student has Scores), then your domain model asks for controller-per-entity type, inherited, as you said, from a generic controller type.
I don't see any reason for App_Start to be generic.
I am using WPF with Entity Framework 6 (DB first), Caliburn.Micro, and MEF.
I am trying to implement IoC in my project. I am an absolute beginner in IoC, and unfortunately, I cant find too many examples where MEF is used with Repository Pattern.
So I have a few repositories, and I have created my Generic Unit of Work like this:
class GenericUoW : IUoW, IDisposable
{
protected readonly DbContext _ctx;
public GenericUoW(DbContext context)
{
_ctx = context;
}
public void Complete()
{
_ctx.SaveChanges();
}
public void Dispose()
{
_ctx.Dispose();
}
}
My actual Unit of Work classes are implemented like this:
class InvoiceUoW : GenericUoW, IInvoiceUoW
{
public InvoiceUoW(DbContext _ctx) : base(_ctx)
{
salesrepo = new SaleRepository(_ctx);
itemsrepo = new ItemRepository(_ctx);
materialrepo = new MaterialRepository(_ctx);
raterepo = new RateRepository(_ctx);
clientrepo = new ClientRepository(_ctx);
taxrepo = new TaxRepository(_ctx);
stockhistoryrepo = new StockHistoryRepository(_ctx);
proformarepo = new ProformaRepository(_ctx);
}
public ISaleRepository salesrepo { get; private set; }
public IItemRepository itemsrepo { get; private set; }
public IMaterialRepository materialrepo { get; private set; }
public IRateRepository raterepo { get; private set; }
public IClientRepository clientrepo { get; private set; }
public ITaxRepository taxrepo { get; private set; }
public IStockHistoryRepository stockhistoryrepo { get; private set; }
public IProformaRepository proformarepo { get; private set; }
}
Now, in my ViewModel, I am doing something like this:
[Export(typeof(InvoiceViewModel))]
class InvoiceViewModel : PropertyChangedBase
{
#region ctor
[ImportingConstructor]
public InvoiceViewModel(IInvoiceUoW invoiceUoW)
{
_uow = invoiceUoW;
Clients = new BindableCollection<Client>(_uow.clientrepo.FetchAll());
}
#endregion
private readonly IInvoiceUoW _uow;
//other properties and methods
}
My question is related to the use of IoC/DI in InvoiceUoW. How do I implement constructor injection in that class? Because each of those repositories in that class has to be instantiated with the same DataContext. How do I make the DataContext a singleton? Please do note that I have several Unit of Work classes, each for one viewmodel.
Register the DbContext instance to be resolved and act like a singleton:
var container = new CompositionContainer(); //Get it from where it belongs
var dbContext = container.GetExportedValue<DbContext>();
container.ComposeExportedValue<DbContext>(dbContext);
For your UoW, MEF doesn't work the same way as Unity, in MEF you rather decorate the implementing type to tell the container it should register it:
[Export(typeof(IUnitOfWork))]
public class MyUnitOfWork : IUnitOfWork
What is the best practice, following DI, to create two separate repository classes...e.g.
public class FirstDbRepo : Repository
public class SecondDbRepo : Repository
That essentially implement the Repository class shown below
namespace MyApp.Persistence
{
public class Repository<T> : IRepository<T> where T : EntityBase
{
public IConfig Config { get; set; }
private Database Database
{
get
{
// Use Config to get connection
};
set;
}
public Repository(IConfig config)
{
Config = config;
}
public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
{
// Use database to get items
}
public T CreateItem(T item)
{
// Use database to create item
}
}
}
But to inject different config values/instances...
public interface IConfig
{
string DatabaseName{ get; }
string DatabaseEndpoint{ get; }
string DatabaseAuthKey{ get; }
}
The first thing I thought of was to create marker interfaces, but wanted to know if this smells...is there a more correct way to do this using DI?
public interface IFirstDbRepo { }
public class FirstDbRepo<T> : Repository<T> where T: EntityBase
{
public FirstDbRepo(FirstConfig config)
: base(config)
{ }
}
public class FirstConfig : IConfig
{
public string DatabaseName{ get { return "MyName" }; } // From web.config
}
And then use a ninject binding for each repo...the consumer could use as follows
public class Consumer() {
private readonly IFirstDbRepo _firstRepo;
public Consumer(IFirstDbRepo firstRepo) {
_firstRepo = firstRepo;
}
}
Bind<IConfig>().To<MyConfigOne>().WhenInjectedInto(typeof(FirstDbRepo));
Bind<IConfig>().To<MyConfigTwo>().WhenInjectedInto(typeof(SecondDbRepo ));
Contextual binding
This question already has answers here:
How to avoid Dependency Injection constructor madness?
(10 answers)
Closed 7 years ago.
I currently have an ASP.Net MVC 5 app that uses 3 external datasources (calls are made to external APIs, responses are deserialized, and mapped to business POCOs).
The app currently uses SimpleInjector to inject concrete repositories for each datasource into a business logic layer for consumption.
The problem is, as more datasources are added (potentially 20-30), the constructor will be huge and injecting all these repositories seems cumbersome.
Is there a better pattern/approach to consuming all the datasources rather than using different repositories?
Would a facade or some other pattern be more appropriate?
Very generic examples:
public class MyObject(){
public IEnumerable<Cat> Cats { get; set; }
public IEnumerable<Dog> Dogs { get; set; }
public IEnumerable<Fish> Fish { get; set; }
}
public class BusinessLogic{
private readonly ISourceARepository _sourceA;
private readonly ISourceBRepository _sourceB;
private readonly ISourceCRepository _sourceC;
public BusinessLogic(ISourceARepository sourceA, ISourceBRepository sourceB, ISourceCRepository sourceC){
_sourceA = sourceA;
_sourceB = sourceB;
_sourceC = sourceC;
}
private Dog MapSourceARecordToDog(SourceARecord record){
var result = new Dog();
if(record != null){
result.Name = record.NameField;
result.Age = record.Age;
}
return result;
}
private Cat MapSourceBRecordToCat(SourceBRecord record){
var result = new Cat();
if(record != null){
result.Name = record.NameField;
result.Weight = record.WeightField;
}
return result;
}
private Fish MapSourceCRecordToFish(SourceCRecord record){
var result = new Fish();
if(record != null){
result.ID = record.IDField;
result.Name = record.NameField;
}
return result;
}
public MyObject GetResults(){
var result = new MyObject();
result.Dogs = _sourceA.GetAll().Select(MapSourceARecordToDog).ToList();
result.Cats = _sourceB.GetAll().Select(MapSourceBRecordToCat).ToList();
result.Fish = _sourceC.GetAll().Select(MapSourceCRecordToFish).ToList();
return result;
}
}
public class SourceARespository : ISourceARepository{
public IEnumerable<SourceAResult> GetAll(){
return new List<SourceAResult>();
}
}
public class SourceBRespository : ISourceBRepository{
public IEnumerable<SourceBResult> GetAll(){
return new List<SourceBResult>();
}
}
public class SourceCRespository : ISourceCRepository{
public IEnumerable<SourceCResult> GetAll(){
return new List<SourceCResult>();
}
}
Update:
This is not a duplicate of the constructor madness question, because in this scenario, a class needs many different datasources, but still has single responsibility. Hence, it warrants its own explanation and answer.
You should only be injecting one repository per entity into a consumer that depends on it. You may also choose to adapt the repository with a business class intermediary.
UPDATE:
Based on the information provided in the question and the problem statement, here is one possible solution. Define your core infrastructure like this:
public abstract class Entity<TEntity, TDomainObject, TIRepository>
where TEntity : Entity<TEntity, TDomainObject, TIRepository>
where TDomainObject : Entity<TEntity, TDomainObject, TIRepository>.BaseDomainObject, new()
where TIRepository : Entity<TEntity, TDomainObject, TIRepository>.IBaseRepository
{
public class BaseDomainObject {}
public interface IBaseRepository
{
IEnumerable<TDomainObject> GetAll();
IEnumerable<T> GetAllMapped<T>(Func<TDomainObject, T> mapper);
}
public class BaseRepository : IBaseRepository
{
public IEnumerable<TDomainObject> GetAll()
{
return new List<TDomainObject>();
}
public IEnumerable<T> GetAllMapped<T>(Func<TDomainObject, T> mapper)
{
return this.GetAll().Select(mapper);
}
}
}
Define your source entities like this:
public class SourceA : Entity<SourceA, SourceA.DomainObject, SourceA.IRepository>
{
public class DomainObject : BaseDomainObject
{
public string Name;
public int Age;
}
public interface IRepository : IBaseRepository {}
public class Repository : BaseRepository, IRepository {}
}
public class SourceB : Entity<SourceB, SourceB.DomainObject, SourceB.IRepository>
{
public class DomainObject : BaseDomainObject
{
public string Name;
public decimal Weight;
}
public interface IRepository : IBaseRepository {}
public class Repository : BaseRepository, IRepository {}
}
public class SourceC : Entity<SourceC, SourceC.DomainObject, SourceC.IRepository>
{
public class DomainObject : BaseDomainObject
{
public Guid Id;
public string Name;
}
public interface IRepository : IBaseRepository {}
public class Repository : BaseRepository, IRepository {}
}
Then define an ISourceRepositoryContext interface like this and add each source repository interface here:
public interface ISourceRepositoryContext
{
SourceA.IRepository SourceARepository { get; }
SourceB.IRepository SourceBRepository { get; }
SourceC.IRepository SourceCRepository { get; }
}
Then define a default implementation for the interface:
public class DefaultSourceRepositoryContext : ISourceRepositoryContext
{
public SourceA.IRepository SourceARepository => new SourceA.Repository();
public SourceB.IRepository SourceBRepository => new SourceB.Repository();
public SourceC.IRepository SourceCRepository => new SourceC.Repository();
}
Define your result transport objects:
public class Dog
{
public string Name;
public int Age;
}
public class Cat
{
public string Name;
public decimal Weight;
}
public class Fish
{
public Guid Id;
public string Name;
}
public class MyObject
{
public IEnumerable<Cat> Cats { get; set; }
public IEnumerable<Dog> Dogs { get; set; }
public IEnumerable<Fish> Fish { get; set; }
}
Then consume the ISourceRepositoryContext in your BusinessLogic class:
public class BusinessLogic
{
protected ISourceRepositoryContext repositories;
public BusinessLogic(ISourceRepositoryContext repositories)
{
this.repositories = repositories;
}
public MyObject GetResults(string param1)
{
return new MyObject()
{
Dogs = this.repositories.SourceARepository.GetAllMapped
(domainObject=>new Dog
{
Age = domainObject.Age,
Name = domainObject.Name
}),
Cats = this.repositories.SourceBRepository.GetAllMapped
(domainObject=>new Cat
{
Name = domainObject.Name,
Weight = domainObject.Weight
}),
Fish = this.repositories.SourceCRepository.GetAllMapped
(domainObject=>new Fish
{
Id = domainObject.Id,
Name = domainObject.Name
}),
};
}
}
I've confirmed that the above compiles under C# 6.0.
I would recommend changing IRepository to IBusiness in Entity and split out the data access concerns from into an IDataAccess interface that only the IBusiness implementors receive via their constructors. And then change the ISourceRepositoryContext to ISourceEntities and change the IRepository properties in that interface to IBusiness properties instead.
The BusinessLogic class is the part that really concerns me. Are you sure this one class won't be taking on too many concerns? Is this supposed to be a UoW class?
For a more complete solution based on similar techniques, check out my answer to this other question: .NET Managing Layers Relationships
I know that this question asked a lot (i think) but i could not find a clear answer in the most smart programmer out there (google).
I have implemented some repositories (not a generic one ) but per entity one.
public class Person
{
public string Name { get; set; }
public int Id { get; set; }
}
public class Product
{
public int ProductId { get; set; }
}
public class PersonRepository
{
ISession Session { get; set; }
public Person GetById(int id)
{
//...
}
public IEnumerable<Person> GetAll()
{
//...
}
}
public class ProductRepository
{
ISession Session { get; set; }
public Product GetById(int id)
{
//...
}
public IEnumerable<Product> GetAll()
{
//...
}
}
public class PostOfficeService
{
ProductRepository _rep1 = new ProductRepository();
PersonRepository _rep2 = new PersonRepository();
public IEnumerable<Person> GetAllPersonWithSameIdAsProduct()
{
_rep1.GetAll().Where( ... )
// ??? i want it to perform the query in the DB and not two queries in app memory
}
}
Should i use the unit of work pattern ?
there are a lot of data and info out there but can't put my finger on the "right" solution
or is it a good solution at all ?
The Unit-Of-Work pattern is to do with transactions - I can't see how it relates to this problem.
GetAllPersonWithSameIdAsProduct should be a method of one of your PersonRepository - or a third, more advanced, repository - since, above the repository level, you don't have access to the session. Another approach is to make your repositories accept ICriteria parameters and use a criteria-builder class to create your complex queries.
However using LINQ-To-NHibernate would make solving these problems easier as the IQueryable implementation becomes your repository, and your Service classes can query using LINQ without any knowledge that they are talking to a database.