I have a repository base class that gets called from my controllers in my mvc application
Each controller gets it own repository
like this
public class ServiceRepository : Bluegrass.Mvc.RepositoryBase<Models.Service>
{
public ServiceRepository()
{
this._db = new iSppms.Models.iSppmsDataContext();
}
}
And gets used like
internal DataAccess.ServiceRepository repository =
new iSppms.DataAccess.ServiceRepository();
public ActionResult Index()
{
var viewData = new ViewData.ServiceIndexViewData(
repository.GetItems<Models.Service>());
return View(viewData);
}
Where I am wanting to do is not have to pass the model through as the RepositoryBase is already of type Models.Service
I am looking for a better way to structure this.
public class RepositoryBase<T> where T : class
{
public DataContext _db;
public List<T> GetItems<T>() where T : class, Interfaces.IModel
{
var table = _db.GetTable<T>();
var data = table.Where(t => !t.Deleted);
return data.ToList();
}
Can you add the IModel bit to RepositoryBase<T>, and make GetItems<T> non-generic? Note: it is already a bad idea to re-use the generic token T (which is different in GetItems):
public class RepositoryBase<T> where T : class, Interfaces.IModel
{
public DataContext _db;
public List<T> GetItems()
{
var table = _db.GetTable<T>();
var data = table.Where(t => !t.Deleted);
return data.ToList();
}
}
Perhaps this Repository Base Class article could help?
Related
I am working on a .Net core project and I have 5 look up tables, so instead of making repository and service for each one I want to make generic repository and generic service for them.
My problem is in implementing FindByID using expressions. I understand the idea behind it but I don't know where or how to use. Any help would be appreciated
Generic Repository Function
private readonly NexusContext _context;
IMapper _mapper;
public GenericRepository(NexusContext context)
{
_context = context;
}
public GenericLookupDTO GetById(Expression<Func<T, bool>> predicate)
{
var obj = _context.Set<T>().Where(predicate);
var objMapped = AutoMapping.mapper.Map<GenericLookupDTO>(obj);
return objMapped;
}
Service Function
private readonly IGenericRepository<T> _genericRepository;
private readonly IUnitOfWork _unitOfWork;
public ConfigurationService(IGenericRepository<T> genericRepository, IUnitOfWork unitOfWork)
{
this._genericRepository = genericRepository;
this._unitOfWork = unitOfWork;
}
List<Errors> errors = new List<Errors>();
try
{
var obj = _genericRepository.GetById(predicate);
if (obj == null)
{
errors.Add(new Errors("404", "Couldn't find configration"));
return new GenericResponse<GenericLookupDTO>(errors, new GenericLookupDTO());
}
await _unitOfWork.CompleteAsync();
return new GenericResponse<GenericLookupDTO>("1", "Success", obj);
}
catch (Exception ex)
{
errors.Add(new Errors(ex.HResult.ToString(), ex.InnerException.Message));
return new GenericResponse<GenericLookupDTO>(errors, new GenericLookupDTO());
}
Controller function
private readonly IConfigurationService<LutNationality> _configurationService;
public NationalityController(IConfigurationService<LutNationality> configurationService)
{
this._configurationService = configurationService;
}
[HttpGet("Id")]
[ProducesResponseType(typeof(GenericLookupDTO), (int)HttpStatusCode.OK)]
public async Task<IActionResult> GetByIdAsync()
{
var result = await _configurationService.GetByIdAsync(//what should i pass here);
if (result.operationSuccess)
return Ok(result);
return BadRequest(result);
}
First look up Table
public partial class LutGender
{
public int Id { get; set; }
public string Value { get; set; }
}
Second look up Table
public partial class LutNationality
{
public int Id { get; set; }
public string Value { get; set; }
}
Generic DTO
public class GenericLookupDTO
{
public int Id { get; set; }
public string value { get; set; }
}
The repository pattern is already implemented by the DbSet<T> and consists in few operations over your entity to store and retrive him from an abstracted data store. Just your entity, it's very important on DDD.
But, I know that sometimes we need to put another layer of abstraction over this, to deal with another databases like nosql, for example.
In this case, usually we create a gereneric repository, and it's needed to supply a way to make operations based on what type this repository is. To accomplish this, we need to define a common interface for our entities with an Id and implement this on those entities:
public interface IEntity
{
Guid Id (get; set;}
}
That way, constraining your generic repository to this type of interface provides you ability to access the Id on the methods.
public class GenericRepository<T> : IGenericRepository<T> where T : IEntity
{
private readonly NexusContext _context;
IMapper _mapper;
public GenericRepository(NexusContext context)
{
_context = context;
}
public GenericLookupDTO GetById(Guid id)
{
var obj = _context.Set<T>().FirstOrDefault(x => x.Id = id);
var objMapped = AutoMapping.mapper.Map<GenericLookupDTO>(obj);
return objMapped;
}
}
I really recomend you to don't return DTOs from repository, if you need to aggregate data from many different entities that are not related, use a different layer of data access, very simplified, and create freely your own queries, using dapper or even EF but projecting directly DTOs.
If the DTO is identical of an entity, in this case use the repository to retrieve the entity and on application layer map this entity to a DTO.
When you have time, take a look at DDD principles to clarify a little bit more those subjects.
Back to your example, on the controller you will need to inject the right type of generic repository, like:
IGenericRepository<Customer> customerRepository
and configure your dependecy injection container to resolve generic types, like:
services.AddTransient<IGenericRepository<>, GenericRepository<>>();
The service will rely just on IGenericRepository<T> as you did.
But, if you want to query freely your entities, I recommend you make use of OData or GraphQl, that will provides you more control over queries.
I'm tried to be very simplistic here, so, I hope that i could clarify things a little bit more for you!
I want to have generic method to get data from database and pass model of how output data should look like.
I wrote simple method:
public IEnumerable<T> GetUsers<T>()
{
Mapper.Initialize(cfg =>
cfg.CreateMap<IQueryable<User>, IQueryable<T>>());
return OnConnect<IEnumerable<T>>(db =>
{
return db.Users.ProjectTo<T>().ToList();
});
}
Now I expected that I can do this:
var users = repo.GetUsers<UserViewModel>(); // it should be IEnumerable<UserViewModel>
var anotherUsers = repo.GetUsers<AnotherUserViewModel>(); // it should be IEnumerable<AnotherUserViewModel>
But I cant reinitialize automapper again. What should I do to make it working?
Initialize automapper only once per application startup.
You should know what types can be mapped from User already at the moment when you design a code in that case you can register all of them at a startup like this:
Mapper.Initialize(cfg => {
cfg.CreateMap<User, UserDto1>();
cfg.CreateMap<User, UserDto2>();
...
cfg.CreateMap<User, UserDtoN>();
});
Even if you will achieve it - it will not make a sense to try to map User to Order, but your architectural design will give that possibility
If you still want to do it(like I wrote in comments) - you can add somekind of marker attribute for Instance - MappableFrom(Type from), mark all DTO objects that can be used in scope of automapper. Then on initialization of your application - scan the assembly for all types that contains that attribute and register in Automapper.
You can use Profile to create all mappers follow this link http://docs.automapper.org/en/stable/Configuration.html
Another approach you can initialize in a static constructor all the mapping you want by using some naming convention
In the below code, I'm mapping from same object type to same object type
// Data or View Models
public class AddressViewModel : BaseViewModel
{
public string Address {get;set;}
public AddressViewModel()
{
this.Address ="Address";
}
}
public class UserViewModel : BaseViewModel
{
public string Name {get;set;}
public UserViewModel()
{
this.Name ="Name";
}
}
public class BaseViewModel
{
}
Repository -- here I'm using same view model you should create Models here
public class CrudRepo
{
public IEnumerable<T> GetData<T>() where T : class, new ()
{
var data = new List<T> { new T() };
return AutoMapper.Mapper.Map<IEnumerable<T>>(data);
}
}
Then in of the static constructor initialize the mappers
static HelperClass()
{
// In this case all classes are present in the current assembly
var items = Assembly.GetExecutingAssembly()
.GetTypes().Where(x =>
typeof(BaseViewModel)
.IsAssignableFrom(x))
.ToList();
AutoMapper.Mapper.Initialize(cfg =>
{
items.ForEach(x =>
{
// Here use some naming convention or attribute to find out the Source and Destination Type
//Or use a dictionary which gives you source and destination type
cfg.CreateMap(x, x);
});
});
}
Now you can create the instance of crud repository and get mapped items
var userRepo = new CrudRepo();
var users = userRepo.GetData<UserViewModel>();
var address = addressRepo.GetData<AddressViewModel>();
Note: As long as property names and types are same the data will be mapped else you have to create ForMember
How do I inject a specific dependency using Ninject when which class to inject is only determined at runtime? I have an interface and implmentations as follows:
public interface ICompanyDAL
{
Company LoadProfile(int companyID);
}
public class TechCompanySqlDAL : ICompanyDAL
{
Company LoadProfile(int companyID)
{
//Call Stored procs related to TechCompany
//Populate Model class TechCompany which is derived from abstract class Company
}
}
public class BankingCompanySqlDAL : ICompanyDAL
{
Company LoadProfile(int companyID)
{
//Call Stored procs related to BankingCompany
//Populate Model class BankingCompany which is derived from abstract class Company
}
}
I have a service class that needs to call one of the two concrete classes as follows.
public class CompanyService
{
private readonly ICompanyDAL companyDAL;
public CompanyHousingService(ICompanyDAL compDAL)
{
this.companyDAL = compDAL;
}
public Company LoadProfile(int companyID, CompanyType type)
{
if(type == CompanyType.Tech)
//Need to call TechCompanyDAL
else if (type == CompanyType.Banking)
//Need to call BankingCompanyDAL
}
}
I don't want Service class to be dependent on any of the concrete classes, because those might change. Also we might add more company typese. So how do I inject ICompanyDAL into the service based on reflection.
I am also open to suggestions on changing the above pattern if anyone explains a better alternative.
There are many approaches to solve that you can use ganerics for example, but one of them is this:
you can change the ctor dependency to IEnumerable<ICompanyDAL>.
so maybe this will works fine to you, see the code below:
public interface ICompanyDAL
{
CompanyType CompanyType {get;}
Company LoadProfile(int companyID);
}
public class TechCompanySqlDAL : ICompanyDAL
{
public CompanyType CompanyType => CompanyType.Tech;
Company LoadProfile(int companyID)
{
//Call Stored procs related to TechCompany
//Populate Model class TechCompany which is derived from abstract class Company
}
}
public class BankingCompanySqlDAL : ICompanyDAL
{
public CompanyType CompanyType => CompanyType.Banking;
Company LoadProfile(int companyID)
{
//Call Stored procs related to BankingCompany
//Populate Model class BankingCompany which is derived from abstract class Company
}
}
Now the Service:
public class CompanyService
{
private readonly IEnumerable<ICompanyDAL>compDALs;
public CompanyHousingService(IEnumerable<ICompanyDAL> compDALs)
{
this.companyDALs = compDALs;
}
public Company LoadProfile(int companyID, CompanyType type)
=> companyDALs.FirstOrDefault(s => s.CompanyType==type)?.LoadProfile(companyID);
}
You can make the ICompanyDAL generic and inject two dependencies into CompanyService like this:
public interface ICompanyDAL<T> where T:Company
{
T LoadProfile(int companyID);
}
public class TechCompanySqlDAL : ICompanyDAL<TechCompany>
{
public TechCompany LoadProfile(int companyID)
{
//Call Stored procs related to TechCompany
//Populate Model class TechCompany which is derived from abstract class Company
}
}
public class BankingCompanySqlDAL : ICompanyDAL<BankingCompany>
{
public BankingCompany LoadProfile(int companyID)
{
//Call Stored procs related to BankingCompany
//Populate Model class BankingCompany which is derived from abstract class Company
}
}
public class CompanyService
{
private readonly ICompanyDAL<BankingCompany> bankingCompanyDAL;
private readonly ICompanyDAL<TechCompany> techCompanyDAL;
public CompanyService(ICompanyDAL<BankingCompany> banking_company_dal, ICompanyDAL<TechCompany> tech_company_dal)
{
bankingCompanyDAL = banking_company_dal;
techCompanyDAL = tech_company_dal;
}
public Company LoadProfile(int companyID, CompanyType type)
{
if (type == CompanyType.Tech)
return techCompanyDAL.LoadProfile(companyID);
else if (type == CompanyType.Banking)
return bankingCompanyDAL.LoadProfile(companyID);
//handle case of invalid type
}
}
And here is how you would register the dependencies and resolve your CompanyService object:
StandardKernel kernel = new StandardKernel();
kernel.Bind<ICompanyDAL<TechCompany>>().To<TechCompanySqlDAL>();
kernel.Bind<ICompanyDAL<BankingCompany>>().To<BankingCompanySqlDAL>();
var service = kernel.Get<CompanyService>();
I am using Entity Framework 6. I use it to generate my classes from an existing database. I am adding some fields and methods to these classes using another partial class. My question is about where shall I put the context.
i.e. I created a new constructor which take my context and create a new object and add it to the
context:
public partial class EntityClass1
{
private readonly EntitiesContext dbContext;
private String customString1;
private bool justInitialized;
public EntityClass1(EntitiesContext dbContext)
{
this.dbContext = dbContext;
dbContext.EntityClass1.Add(this);
customString1 = "voila";
justInitialized = true;
}
public MethodUpdateString()
{
customString1 = "UPDATED";
var entity2 = new EntityClass2();
entity2.EntityClass1Id = this.Id;
dbContext.EntityClass2.Add(entity2);
dbContext.SaveChanges();
{
}
public partial class EntityClass2
{
//Some code here
}
public MainClass{
static void Main(){
using (var dbContext = new EntitiesContext())
{
//other operations on the context here
var e1 = new EntityClass1(dbContext);
e1.MethodUpdateString();
//other operations on the context here
}
}
}
I don't why, but I am not really comfortable with this possible implementation. Will it better for example to add a context parameter to the method MethodUpdateString() ? Also because I do a SaveChamges I end the transaction.
Your instincts are correct, both in trying to use constructor injection and in not being comfortable having data access logic inside your model class. An alternative implementation would be this:
public partial class EntityClass1Service
{
private readonly EntitiesContext dbContext;
public EntityClass1Service(EntitiesContext dbContext)
{
this.dbContext = dbContext;
}
public MethodUpdateString(EntityClass1 entityClass1Object)
{
entityClass1Object.CustomString1 = "UPDATED";
dbContext.EntityClass1.Add(entityClass1Object);
var entity2 = new EntityClass2();
entity2.EntityClass1Id = entityClass1Object.Id;
dbContext.EntityClass2.Add(entity2);
dbContext.SaveChanges();
}
}
You might also want to add a try-catch block inside the MethodUpdateString and maybe change customString1 to be a public property.
What is the general advice on serializing something like this in MongoDb
public class BaseCategorization<T> where T : BaseCategory
{
public BaseCategorization()
{
Type = typeof(T).Name;
}
public BaseCategorization(int id)
{
Id = id;
Type = typeof(T).Name;
}
...
}
I use it like this:
_documentsProvider.Save<BaseCategorization<ProductCategory>>(newProductCategorization);
where ProductCategory : BaseCategory and BaseCategory is abstract.
The above seems to work, only problem is the strange name of the resulting collection, BaseCategorization'1, and the fact that I don't know whether this design is fine by MongoDb terms.
You certainly can store all of your documents in one collection, however it is probably easier and cleaner in the long run to only store one type in a collection (from a C# perspective). You can do this by creating a class with an Extension Method on MongoDatabase.
public static class MyDatabase
{
public static MongoCollection<T> GetCollection<T>(this MongoDatabase db)
{
var name = typeof(T).Name;
return db.GetCollection<T>(name);
}
}
Then you can just call GetCollection with your type on it and the name will be hidden from your general code. You can also create something like this to abstract things a little bit further:
public class MyDatabase
{
private MongoDatabase _db;
public MyDatabase(MongoDatabase db)
{
_db = db;
}
public MongoCollection<object> Objects
{
get
{
return _db.GetCollection<object>();
}
}
}
With this you can just do
var client = new MongoClient();
var server = client.GetServer();
var db = server.GetDatabase("MyDb");
var myDb = new MyDatabase(db);
myDb.Objects.Find();
This Find will map to execute against the Objects collection, simply replace <object> with your type and give the collection a name.