Repository pattern on multiple data provider/ORM? - c#

Let just say I have the following data models:
public class Account
{
public string Username { get; set; }
public string Password { get; set; }
}
public class Configuration
{
public string Key { get; set; }
public string Value { get; set; }
}
For now, each of them has their own repository for data access, and uses entity framework as its unit of work/DbContext. I'm planning to pull out the Configuration part out of the entity frame and use Redis or Memcached as its data access. I might even to switch the EF to NHibernate or no ORM at all, and I might switch the database to MongoDB or CouchDB.
What is the good way to do this? To be ignorant of all those lower layer stuff in my business logic? What kind of pattern to use? Is it possible or is it just bad things to design for changes like this?
Thanks :)

As stated in the previous post, you should go the "way of the Interface".
I personally do not implement directly the repository for each orm but I use a little variation.
Using your example...
public interface IAccountRepository
{
Account Get(int id);
void Delete(int id);
...other method...
}
then you create your repository
public class AccountRepository : IAccountRepository
{
private readonly IUnitofWork unitofWork;
public AccountRepository(IUnitofWork unitofWork)
{
this.unitofWork = unitofWork;
}
//Implement interface method
public Account Get(int id)
{
//some logic or just the call to the unit of work
return unitofWork.Get(id);
}
}
I am happy with this solution because I end up with only one repository that 90% of the time use linq to query so I don't have to write the sql for each unit of work and every time I have to write a "GetAllProducts" with paging I do not have to write the same code (and tests) for every unit of work, but only for my repository. This is a simple example obviously so I hope you get the idea.
You can make a RepositoryBase that implement a method Find() or Query() which use linq.
Then with your Castle Windsor or ninject or whatever you can inject the unit of work you prefer. Hope it helps.
Update:
a sample of my UnitofWorkBase that implement nhibernate is something similar:
public class NHUnitofWork<T> : IUnitofWork<T> where T : EntityBase
{
protected INHSessionBuilder SessionBuilder { get; private set; }
public NHPersistorBase(INHSessionBuilder sessionBuilder)
{
SessionBuilder = sessionBuilder;
}
public T Get(int id)
{
T result = null;
ISession session = SessionBuilder.GetSession();
using (ITransaction transaction = session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))
{
try
{
result = (T)session.Get(typeof(T), id);
transaction.Commit();
}
finally
{
if (transaction.IsActive)
transaction.Rollback();
}
}
return result;
}
public IQueryable<T> Find()
{
return SessionBuilder.GetSession().Query<T>();
}
}

Use an interface.
public class IAccountRespository
{
public Account LoadAccountByUsername(String Username);
public void DeleteAccont(Account a);
public void SaveAccont(Account a);
.
.
.
...more methods
}
then you implement this interface on every data access object (ef,mongdb, etc. etc).
In your business logic code you use just the interface and not the acual object.
i use the factory pattern to create the data access objects, but you can use every IoC pattern.

Related

How to implement expressions in Generic Repository?

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!

Should I transform Entity (Persistent) objects to DTO objects?

My project is layered as follows:-
DAL (Entity) --> BLL (DTO) --> ApplicationComponent (ViewModel).
There will be multiple components of application (ApplicationComponent) which will access BLL. Components include windows services, web services, web API and MVC controller.
I am transforming NHibernate Entity objects to DTO objects while passing them from DAL to BLL. While passing this state to ApplicationComponent, BLL again converts it to ViewModel.
This helps me separate the concerns and how data is handled in each layer. I am not in favor of returning NHibernate Entity object to view for following reasons: -
Data get exposed to UI that I want to hide (or only expose if needed) like passwords, user type, permission etc.
On references/joins, NHibernate executes additional queries when property is accessed which nullify the use of lazy loading.
Unnecessary data exposed to user (of Entity) creates confusion and gap for bugs.
Persistence implementations leaking into BLL/UI. Entity is not designed for UI. It cannot serve UI in all cases.
We use attributes on DTO properties for user input validation which looks odd with Entity.
I am facing following problems with this approach: -
Biggest and obvious problem is redundant objects with similar members and functionality.
I have to write mapper methods in each layer to transform object. This could be minimized by using AutoMapper or something similar; but it does not fully resolve problem.
Questions:-
Is this an over separation and should be avoided (at least minimized)?
If this approach is correct, I do not see any simple way to fully bypass two problems I stated above. Please suggest.
If this approach is incorrect, please suggest corrections.
References:-
Link1 suggests to transfer Entity object to view which in my understanding not a good idea.
Link2 suggests to map Entity with DTO that I am already doing.
Link3 does not help.
Link4 suggests using something like auto mapper tools which is OK. But it still does not solve the problem completely.
Link5 is great post. It explains why those should be separate which I agree. It does not comment on how to minimize the overhead caused by it.
Link6 is not helpful again.
Link7 is an excellent answer which suggests use Entity as is in UI if possible. It still does not apply to most of my project.
Linl8 is another excellent resource that suggest to go on mapping two way as I am doing now. It still does not suggest a way to minimize overhead.
Have you considered creating a shared interface between the DTO and the Entity? You should not tightly couple your ORM to the rest of your application. Or in fact use anything other than interfaces between them if at all possible.
You could, in theory, have a separate project that just holds the contract/abstractions of what you expect to be passed around. To minimize mapping overhead and to leave it open for the extension you can ensure that the entity implements the interface as expected (omitting what is not needed), and in cases where you need a bespoke DTO you can create a model with mapping using the interfaces.
There is some overhead when adding extra interface projects but it will keep your code cleaner and more maintainable in the long run.
namespace Data
{
public class FakeRepo : IFakeRepo
{
public IThisIsAnEntity GetEntity()
{
return new ThisIsAnEntity();
}
}
public class ThisIsAnEntity : IThisIsAnEntity
{
public string HiddenField { get; set; }
public long Id { get; set; }
public string SomeField { get; set; }
public string AnotherField { get; set; }
}
}
namespace Data.Abstractions
{
public interface IFakeRepo
{
IThisIsAnEntity GetEntity();
}
}
namespace Abstractions
{
public interface IThisIsAnEntity : IThisIsAnSlimmedDownEntity
{
string SomeField { get; set; }
}
public interface IThisIsAnSlimmedDownEntity
{
long Id { get; set; }
string AnotherField { get; set; }
}
}
namespace Services.Abstractions
{
public interface ISomeBusinessLogic
{
IThisIsAnEntity GetEntity();
IThisIsAnSlimmedDownEntity GetSlimmedDownEntity();
}
}
namespace Services
{
public class SomeBusinessLogic : ISomeBusinessLogic
{
private readonly IFakeRepo _repo;
public SomeBusinessLogic(IFakeRepo repo)
{
_repo = repo;
}
public IThisIsAnEntity GetEntity()
{
return _repo.GetEntity();
}
public IThisIsAnSlimmedDownEntity GetSlimmedDownEntity()
{
return _repo.GetEntity();
}
}
}
namespace UI
{
public class SomeUi
{
private readonly ISomeBusinessLogic _service;
public SomeUi(ISomeBusinessLogic service)
{
_service = service;
}
public IThisIsAnSlimmedDownEntity GetViewModel()
{
return _service.GetSlimmedDownEntity();
}
public IComposite GetCompositeViewModel()
{
var dto = _service.GetSlimmedDownEntity();
var viewModel = Mapper.Map<IThisIsAnSlimmedDownEntity, IComposite>(dto);
viewModel.SomethingSpecial = "Something else";
return viewModel;
}
}
public class SomeViewModel : IComposite
{
public long Id { get; set; }
public string AnotherField { get; set; }
public string SomethingSpecial { get; set; }
}
}
namespace UI.Abstractions
{
public interface IComposite : IThisIsAnSlimmedDownEntity, ISomeExtraInfo
{
}
public interface ISomeExtraInfo
{
string SomethingSpecial { get; set; }
}
}
nhibernate is one of those orm`s that allow you to avoid having DAL entities and it will be better for performance to avoid extra mapping from BLL TO DAL, but if it is not critical for you, it will be better to keep it at as it is to have application layers loose coupled

Abstract away the DAL from Entity Framework implementation

First of all I'm sorry if this is going to be a long post, but I don't know how to explain the problem in the correct way without the required details.
I'm having troubles finding a way to abstract my DAL from an Entity Framework implementation. The project I'm working on is very small, but if in future I'd want to switch to another ORM like NHibernate, or just plain ADO.NET, I'd like to write code just for the implementation, not the entire DAL.
Say I have these entities in my MyWallet.DAL:
public interface IWallet {
long Id { get; set; }
float TotalAmountOfMoney { get; set; }
long CurrencyId { get; set; }
ICurrency Currency { get; set; }
DateTime RecordedOn { get; set; }
ICollection<IMoneyMovement> MoneyMovements { get; set; }
}
public interface ICurrency {
long Id { get; set; }
char Symbol { get; set; }
string Code { get; set; }
string Description { get; set; }
}
public interface IMoneyMovement {
long Id { get; set; }
float Amount { get; set; }
string Description { get; set; }
long WalletId { get; set; }
IWallet Wallet { get; set; }
DateTime RecordedOn { get; set; }
DateTime MovedOn { get; set; }
}
As you can see these are plain interfaces which I plan to implement on another library which will contain the actual Entity Framework implementation (say MyWallet.DAL.EntityFramework). Of course I'm going to decorate the entities implementation with Entity Framework specific attributes as [Key] or [ForeignKey] and stuff like that.
I also defined some repository in MyWallet.DAL like IWalletRepository, IMoneyMovementRepository, ICurrencyRepository to gain access to the entities. Actually I don't know if this is the right way to design access to the entities. Of course I also defined factories to get the concrete implementation of the entities.
In my business layer I defined services to handle the object request, work with the DAL entities and return a business object, like this:
public class WalletService {
private readonly IWalletRepository _walletRepository;
private readonly IWalletFactory _walletFactory;
public WalletService(IWalletRepository walletRepository,
IWalletFactory walletFactory) {
_walletRepository = walletRepository;
_walletFactory = walletFactory;
}
public CreatedWallet CreateWallet(CreateWalletRequest request) {
var wallet = _walletFactory.Create();
wallet.CurrencyId = request.CurrencyId;
wallet.TotalAmountOfMoney = request.TotalAmountOfMoney;
wallet.RecordedOn = DateTime.Now;
_walletRepository.Create(wallet);
_walletRepository.SaveChanges();
return new CreatedWallet {
Id = wallet.Id
}
}
}
I thought this was going to work seamlessly, or at worst - in a situation when I've got more than one repository - I could share the DataContext so I'd need to fire the SaveChanges method on just one to reflect the changes on the database.
The problem is with the repository implementation, in this case I'll continue with Entity Framework:
public class EFDataContext : DbContext {
public EFDataContext() : base ("name=MyConnectionString") {
}
public virtual DbSet<EFWallet> Wallets { get; set; }
public virtual DbSet<EFMoneyMovement> MoneyMovements { get; set; }
public virtual DbSet<EFCurrency> Currencies { get; set; }
}
public class EFWalletRepository : IWalletRepository {
private readonly EFDbContext _dataContext;
public EFWalletRepository(EFDbContext dataContext) {
_dataContext = dataContext ?? new EFDbContext();
}
public int SaveChanges() {
return _dataContext.SaveChanges();
}
public void Dispose() {
_dataContext.Dispose();
}
public void Create(IWallet wallet) {
...???
}
}
Now that's the problem: how do I work with interfaces when the DataContext knows only about concrete implementations? Am I doing this all wrong?
UPDATE:
Ok so, basically, as stated out by #TomTom, why fight Entity Framework when you could just embrace its power? I guess I'll just let EF be the abstraction. In fact, by letting EF act as the DAL, you can just focus on the business logic of your project.
And to put it all together and respond to #tdragon regarding the repositories / unit of work issue: yes, I could either wrap multiple repositories inside an unit of work or simply let the DbContext be the unit of work:
public class EFWalletRepository : IWalletRepository {
private readonly EFDbContext _dataContext;
public EFWalletRepository() {
_dataContext = new EFDbContext();
}
public void Dispose() {
_dataContext.Dispose();
}
public IEnumerable<Wallet> Wallets {
get { return _dataContext.Wallets; }
}
public void SaveWallet(Wallet wallet) {
if (wallet.Id == 0) {
_dataContext.Wallets.Add(wallet);
} else {
var databaseEntry = _dataContext.Wallets.Find(wallet.Id);
//update properties
}
_dataContext.SaveChanges();
}
}
Simply speaking: yes, you do it wrong. You introduce a bad abstraction (that costs you dearly in functionality) "because of". EF already is an abstraction.
Any abstraction on top of it will cost you in terms of functionality used - which in terms of databases comes with a big performance impact. Want an example? "Include" to preload navigation properties (instead of lazy loading). You will have to work around this and a lot of more detailed behavior that is ORM specific - for the gain of having what? And if you give up on those higher more specific functions your performance WILL suffer.
I can't see any reason to abstract your model (entities). Do you expect them to change when you change the way you access your database?
But if you want to keep it that way, you can make your repository interfaces generic, and pass the concrete entity type when defining repository, so you would end up with:
public class EFWalletRepository : IWalletRepository<EFWallet>
{
public void Create(EFWallet wallet)
{
_dataContext.Add(wallet);
}
}
Other suggestions:
You should not expose sets for your model properties. It's against OOP rules - you should rather expose some methods to manipulate the objects, the state should be more internal.
You probably should not add SaveChanges() method to your repository - this should be a "unit of work" job to commit all changes to the database.
You would face a problem when you would use more than one repository in your service layer, as you create a new DbContext for repository, when you should have one for single "unit of work".

How to make Linq2Sql work with my models

I work on a project where we was using SqlConnection, SqlCommand and plain SQL to access repository. Now, I am trying to migrate to Linq2Sql and I want to use the same models. How can I achieve this?
I will reduce the project structure to the minimal meaningful example.
Let's say I have the following classes:
namespace Model
{
public class User
{
public int Id { get; set; }
}
}
All models in Model namespace are one-in-one copy of database entities.
namespace Repository
{
public class UserRepository
{
private _sqlConnectionHelper = new SqlConnectionHelper();
public User GetUser()
{
var reader = _sqlConnectionHelper
.ExecuteAndReturnReader("SELECT * FROM [dbo].[Users]");
while (reader.Read())
{
return new User
{
Id = (int)reader["Id"]
};
}
return null;
}
}
}
Now I am trying to migrate to Linq2Sql. I have created a MyContext.dmbl file with User table in Repository project. It has generated the following class:
namespace Repository
{
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Users")]
[global::System.Runtime.Serialization.DataContractAttribute()]
public partial class User: INotifyPropertyChanging, INotifyPropertyChanged
{
private int _ID;
public int ID
{
get
{
return this._ID;
}
set
{
if ((this._ID != value))
{
this.OnIDChanging(value);
this.SendPropertyChanging();
this._ID = value;
this.SendPropertyChanged("ID");
this.OnIDChanged();
}
}
}
// Some other methods
}
}
Now, the problem is that I have a lot of of entities, repositories, models etc. I don't want to change the whole project to use new generated models but not mine from Model namespace. How can I make Linq2Sql work with my models?
It also affects my architecture because in case of these models, the entity and the repository is the same object. I don't need my entities to be CRUD objects. I just want to make minimal changes to project and only use convenient LINQ requests instead of plain SQL like this:
namespace Repository
{
public class UserRepository
{
private MyContextDataContext _myContext = new MyContextDataContext();
public User GetUser()
{
return _myContext.Users.FirstOrDefault();
}
}
}
Or I just don't understand something about purpose and logic of Linq2Sql and it is how it only works like?
Of course, I can write converters or use reflection and make a copy of object property-by-property but it doesn't sound like a good solution.
Ok. Finally, I have found an answer which is pretty simple - Linq2Sql is not a library I was looking for.
There are different approaches for object-relational mapping: code-first, database-first, model-first.
Here is the good StackOverflow article about their differences.
Now, when I learned it, what I have described in my question could be easily rephrased as "how can I make Linq2Sql be code-first". The answer is simple - I cannot do this.
As a result of some investigations, I have understood that I was looking for Entity Framework which perfectly fit in my project.
Now, my repository looks like this:
namespace Repository
{
public MyContextDataContext : DbContext
{
public DbSet<User> Users { get; set; }
}
public class UserRepository
{
private MyContextDataContext _myContext = new MyContextDataContext();
public User GetUser()
{
return _myContext.Users.FirstOrDefault();
}
}
}

Mapping database entities to domain entities via repositories - static property or separate service?

I am working on an application where my database schema does not match up well to my domain model, and modifications to the database schema are not under my control. Because of this, I end up doing a lot of mapping in my repository calls, and I have many concrete repos to handle the mapping to and from the database (using entity framework database-first). What I am looking for is an elegant way to make calls to my repositories based on the domain entity object type. Thus far, the domain model itself is still very anemic, as we are still in the process of defining business rules.
I have seen an example elsewhere (can't recall the link) where the repository calls were passed through the domain entities via a static property, but I do not know if this will present threading issues or whether it violates any domain model principles, especially if we decide to implement DI/IoC down the road.
Here is an example of what I have so far. For the sake of brevity, I have simplified the mapping calls to the database, as the mapping in the actual application is more complex.
Repository example:
public interface IRepository<T>
{
T GetById(int id);
void Save(T entity);
}
public abstract class RepositoryFactory<T> : IRepository<T>
{
protected MyDbContext db;
protected int userId;
protected RepositoryFactory()
{
this.db = new MyDbContext();
this.userId = WebSecurity.GetCurrentUser().UserId;
}
public abstract T GetById(int id);
public abstract void Save(T entity);
}
public class CustomerRepository : RepositoryFactory<Customer>
{
public override void Save(Customer customer)
{
var entity = db.customers.FirstOrDefault(p => p.customerid == customer.Id && p.users.userid == userId);
if (entity == null) return; // TODO: Add error trapping
// Mapping (lots of reshaping happening here)
entity.customername = customer.Name;
entity.customeraddress = customer.Address;
// ...
// Save changes to DB
db.Entry(entity).State = EntityState.Modified;
db.SaveChanges();
}
public override Customer GetById(int id)
{
var entity = db.customers.FirstOrDefault(p => p.customerid == id && p.users.userid == userId);
if (entity == null) return null; // TODO: Add error trapping
return new Customer
{
Name = entity.customername,
Address = entity.customeraddress,
// ...
};
}
}
Domain Entity example:
public class Entity { public int Id { get; set; } }
public class Customer : Entity
{
public string Name { get; set; }
public string Address { get; set; }
// Does this violate any domain principles?
public static IRepository<Customer> Repository
{
get { return new CustomerRepository(); }
}
}
With this code, from my controller I can do something like:
Customer customer = Customer.Repository.GetById(id);
Instead of:
IRepository<Customer> repo = new CustomerRepository();
Customer customer = repo.GetById(id);
This seems like a very elegant solution to my problem, and it also keeps me from needing to include the Repository namespace in my controllers (MVC). If this smells funny and there is a better way to handle this, I'd love to learn. The only other thing I can think of is creating a separate crud service to handle my repository calls, but I imagine for that I would need a dictionary or hash table to map my concrete repos to my domain model objects, and that seems like it would be a maintenance nightmare.
I'd suggest using an inversion of control (dependency injection) container and injecting your repositories into your controllers or wherever. This way you can use them like this:
public class HomeController : Controller
{
private readonly IRepository<Customer> _customerRepository;
public HomeController(IRepository<Customer> customerRepository)
{
_customerRepository = customerRepository;
}
public ActionResult Index(int id)
{
var customer = _customerRepository.GetById(id)
return View(customer);
}
}
This way, if you ever need to replace CustomerRepository class, or need to have multiple versions (say CustomerRepositoryEntityFramework or CustomerRepositoryNHibernate) you can simply replace a new class inheriting from IRepository and your controller code will still continue to work with no change.
I recommend using Castle Windsor, or Ninject, or one of the many other IoC containers.
Also, you generally want to keep your domain entities as poco's (Plain Old CLR Object). This means separating everything out of your entities including validation, business rules, etc. and simply having only its properties. This allows you to pass your domain entities through the pipeline more easily, specially since you are in the early stages of development. This will offer you the most flexibility in the future.

Categories

Resources