Greatings,
My project designed base on N-Tier Architecture. There are Core, Repository and Service layers.I have to many tables to join each other.And I would like to use Linq to support multiple sql database.
Here is my IRepository interface;
public interface INodeRepository :IGenericRepository<Node>
{
Task<IEnumerable<Node>> GetAllAsync();
}
I am not sure that " Task<IEnumerable> GetAllAsync(); " this method is right.
Here is the Repository
public class NodeRepository : GenericRepository<Node>, INodeRepository
{
public NodeRepository(AppDbContext context) : base(context)
{
}
public async Task<IEnumerable<Node>> GetAll()
{
return await _context.Nodes.Join()
}
}
I actually dont even know how to fill it.I will also make a implementation to my Iservice.
Any help ?
Related
We are running a few Stateless Reliable Services and are having performance issues with service-to-service communication using the reverse proxy (http://localhost:19081/{app}/{svc}/bleh). Without getting into the details there, we are looking into using remoting as described here: https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication-remoting
However, I am having a hard time figuring out how I would expose the API methods in the service type class, as they currently exist in our controllers. The controllers, via dependency injection, get the repository instances needed, etc..., so I'm spinning my wheels on how to get this accomplished without some sort of redundant instances or circular dependency.
I'm sitting here staring at this on "PersonService.cs":
internal sealed class PersonService: StatelessService, IPersonService
{
public PersonService(StatelessServiceContext context)
: base(context)
{ }
...
public PersonResponse GetPersonFromDb()
{
//lost here :(
}
Where my controller, which works fine, has:
public PersonController(IPersonRepository personRepository)
{
_personRepository = personRepository;
}
...
public IActionResult GetPerson()
{
var personResponse = _dbRepository.GetPerson();
return new ObjectResult(personResponse);
}
D:
Can't you pass the repository to your service, similar to this?
public PersonService(StatelessServiceContext context, IPersonRepository personRepository)
: base(context)
{
_personRepository = personRepository;
}
public PersonResponse GetPersonFromDb()
{
var personResponse = _personRepository.GetPerson();
return personResponse;
}
I have read as many of the posts on Stackoverflow as I can find with regards the use of a Unit of Work pattern within
an ASP.Net MVC 3 application which includes a Business Layer. However, I still have a couple of questions with
regards this topic and would greatly appreciate any feedback people can give me.
I am developing an ASP.Net MVC 3 Web application which uses EF 4.1. I will be using both the Repository and
Unit of Work Patterns with this project similar to how they are used in this great tutorial
The difference in my project is that I need to also include a Business Layer (separate project in my solution) in order to
carry out the various business rules for the application. The tutorial mentioned above does not have a Business layer, and
therefore creates an instance of the Unit of Work class from the controller
public class CourseController : Controller
{
private UnitOfWork unitOfWork = new UnitOfWork();
However, my question is, where should I create the instance of the Unit of Work class if I have a Business Layer?
I personally think it should be created in my controller and then injected into the Business Layer like so:
public class PeopleController : Controller
{
private readonly IUnitOfWork _UoW;
private IPersonService _personService;
public PeopleController()
{
_UoW = new UnitOfWork();
_personService = new PersonService(_UoW);
}
public PeopleController(IUnitOfWork UoW, IPersonService personService)
{
_UoW = UoW;
_personService = personService;
}
public ActionResult Edit(int id)
{
Person person = _personService.Edit(id);
return View(person);
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
private BlogEntities _context = new BlogEntities();
private PersonRepository personRepository = null;
public IPersonRepository PersonRepository
{
get
{
if (this.personRepository == null)
{
this.personRepository = new PersonRepository(_context);
}
return personRepository;
}
}
public void Save()
{
_context.SaveChanges();
}
public class PersonService : IPersonService
{
private readonly IUnitOfWork _UoW;
public PersonService(IUnitOfWork UoW)
{
_UoW = UoW;
}
public Person Edit(int id)
{
Person person = _UoW.PersonRepository.GetPersonByID(id);
return person;
}
public class PersonRepository : IPersonRepository
{
private readonly BlogEntities _context;
public PersonRepository(BlogEntities context)
{
_context = context;
}
public Person GetPersonByID(int ID)
{
return _context.People.Where(p => p.ID == ID).Single();
}
I have read others saying that the Unit of Work instantiation should not be in the Controller, but created in the Service Layer
instead. The reason why I am not so sure about this approach is because my Controller may have to use several different
Service Layers in one business transaction, and if the Unit of Work instance was created inside each Service, it would result in several
Unit of Work instances being created, which defeats the purpose, ie, one Unit of Work per business transaction.
Maybe what I have explained above is wrong, but if so, I would greatly appreciate if someone could put me right.
Thanks again for your help.
I think you have a couple of changes to make:.
Allow your DI container to inject a UnitOfWork instance into your Service classes in their constructors, and leave it out of your Controller altogether.
If your DI container supports it (Ninject does, for example), configure your UnitOfWork to be managed on a per-request basis; this way your services will be handed a distinct UnitOfWork for each request, and you're all done. Or...
If your DI container does not support per-request lifetimes, configure it to manage the UnitOfWork as a singleton, so every Service class gets the same instance. Then update your UnitOfWork to store its Entities object in a data store which stores objects on a per-request basis, for example in HttpContext.Current.Items, as described here.
Edit 1
Regarding where the UnitOfWork should be injected; I'd say the Service layer is the correct place. If you imagine your system as a series of layers where the outer layers deal with user interactions and the lower layers deal with data storage, each layer should become less concerned with users and more concerned with data storage. UnitOfWork is a concept from one of the 'lower-level' layers and Controller is from a higher-level layer; your Service layer fits between them. It therefore makes sense to put the UnitOfWork into the Service class rather than the Controller.
Edit 2
To elaborate on the UnitOfWork creation and it's relationship to HttpContext.Current.Items:
Your UnitOfWork would no longer hold a reference to an Entities object, that would be done through the HttpContext object, injected into the UnitOfWork behind an interface like this:
public interface IPerRequestDataStore : IDisposable
{
bool Contains(string key);
void Store<T>(string key, T value);
T Get<T>(string key);
}
The HttpContext object would then implement IPerRequestDataStore like this:
public class StaticHttpContextPerRequestDataStore : IPerRequestDataStore
{
public bool Contains(string key)
{
return HttpContext.Current.Items.Contains(key);
}
public void Store<T>(string key, T value)
{
HttpContext.Current.Items[key] = value;
}
public T Get<T>(string key)
{
if (!this.Contains(key))
{
return default(T);
}
return (T)HttpContext.Current.Items[key];
}
public void Dispose()
{
var disposables = HttpContext.Current.Items.Values.OfType<IDisposable>();
foreach (var disposable in disposables)
{
disposable.Dispose();
}
}
}
As an aside, I've called it StaticHttpContextPerRequestDataStore as it uses the static HttpContext.Current property; that's not ideal for unit testing (another topic altogether), but at least the name indicates the nature of its dependency.
Your UnitOfWork then passes the IPerRequestDataStore it's given to each of its Repository objects so they can access the Entities; this means that no matter how many UnitOfWork instances you create, you'll use the same Entities object throughout a request because it's stored and retrieved in the IPerRequestDataStore.
You'd have an abstract base Repository which would use its IPerRequestDataStore to lazy-load its Entities object like this:
public abstract class RepositoryBase : IDisposable
{
private readonly IPerRequestDataStore _dataStore;
private PersonRepository personRepository;
protected RepositoryBase(IPerRequestDataStore dataStore)
{
this._dataStore = dataStore;
}
protected BlogEntities Context
{
get
{
const string contextKey = "context";
if (!this._dataStore.Contains(contextKey))
{
this._dataStore.Store(contextKey, new BlogEntities());
}
return this._dataStore.Get<BlogEntities>(contextKey);
}
}
public void Dispose()
{
this._dataStore.Dispose();
}
}
Your PeopleRepository (for example) would look like this:
public class PeopleRepository : RepositoryBase, IPersonRepository
{
public PeopleRepository(IPerRequestDataStore dataStore)
: base(dataStore)
{
}
public Person FindById(int personId)
{
return this.Context.Persons.FirstOrDefault(p => p.PersonId == personId);
}
}
And finally, here's the creation of your PeopleController:
IPerRequestDataStore dataStore = new StaticHttpContextDataStore();
UnitOfWork unitOfWork = new UnitOfWork(dataStore);
PeopleService service = new PeopleService(unitOfWork);
PeopleController controller = new PeopleController(service);
One of the central concepts here is that objects have their dependencies injected into them via their constructors; this is generally accepted as good practice, and more easily allows you to compose objects from other objects.
I'm building a new project off the service repository pattern detailed here. It seems to work well in the most basic of examples. In more complex scenarios is it acceptable to mix the objects in the service \ repository layers?. For example say there is a User repository and service and I want to be able to create an audit for the creation of a user, I would think this would go in the service layer.
If I follow the article the service automatically creates the user repository object in the constructor. Adding a audit would mean adding audit CRUD methods to the user repository? Does that make sense to do that?
public UserService(IValidationDictionary validationDictionary, IUserRrepository repository)
{
_validatonDictionary = validationDictionary;
_repository = repository;
}
in my experience you dont need repositories for each entity type. Just create one repository for the whole model, and then use linq queries over it. EF already provides implementation of that repository, you can create a custom interface like shown below and implement it over that repository ..
public interface IDataContext
{
void Add<T>(T entity) where T : BaseEntity;
void Delete<T>(T entity) where T : BaseEntity;
IQueryable<T> Find<T>(Expression<Func<T, bool>> where) where T : BaseEntity;
int SaveChanges()
}
where your base entity is your base class for all repositories.
most of the linq you would write would be pretty straighforward, but for the complicated ones, just write Utility classes
in our implementation the class derived from DbContext implements this interface, and all the auditing is done through the Save Method using the ChangeTracker
A sample implementation of EF 4.2 is below ...
public class MyContext : DbContext, IDataContext
{
static MyContext ()
{
Database.SetInitializer<MyContext >(null);
}
public T GetById<T>(int id) where T : BaseEntity
{
return this.Set<T>().SingleOrDefault(i => i.Id == id);
}
public void Add<T>(T entity) where T : BaseEntity
{
this.Set<T>().Add(entity);
}
public void Delete<T>(T entity) where T : BaseEntity
{
this.Set<T>().Remove(entity);
}
public IQueryable<T> Find<T>(System.Linq.Expressions.Expression<Func<T, bool>> where) where T : BaseEntity
{
return this.Set<T>().Where(where);
}
public override int SaveChanges()
{
this.SetAuditValues();
return base.SaveChanges();
}
private void SetAuditValues()
{
var addedEntries = this.ChangeTracker.Entries().Where(e => e.State == System.Data.EntityState.Added);
var currentUser = this.GetCurrentUser();
foreach (var addedEntry in addedEntries)
{
var entity = addedEntry.Entity as BaseEntity;
if (entity != null)
{
entity.CreateDateTime = DateTime.Now;
entity.CreateUser = currentUser;
entity.ModDateTime = DateTime.Now;
entity.ModUser = currentUser;
}
}
var modifiedEntries = this.ChangeTracker.Entries().Where(e => e.State == System.Data.EntityState.Modified);
foreach (var modEntry in modifiedEntries)
{
var entity = modEntry.Entity as BaseEntity;
if (entity != null)
{
entity.ModDateTime = DateTime.Now;
entity.ModUser = currentUser;
}
}
}
}
You can surely have one repository/service layer handle more than one entity if it falls within the purpose or domain of that service. Generally in simple examples - you are correct, you don't see this but there is no reason you can include another entity.
Now in regards to your audit, why not just call off to your audit service layer instead of including an audit object (if thats what you meant)
I was working on a Unit of Work implementation that works both in Entity Framework 4.1 and NHibernate. Find below the skeleton of my implementation details
IUnitOfWork definition
public interface IUnitOfWork
{
IRepository<LogInfo> LogInfos { get; }
IRepository<AppInfo> AppInfos { get; }
void Commit();
void Rollback();
}
IRepository definition
public interface IRepository<T> where T : class, IEntity
{
IQueryable<T> FindAll();
IQueryable<T> FindWhere(Expression<Func<T, bool>> predicate);
T FindById(int id);
void Add(T newEntity);
void Remove(T entity);
}
Implementation of UoW in NHibernate
public class NHibernateUnitOfWork : IUnitOfWork, IDisposable
{
public ISession Session { get; private set; }
public NHibernateUnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession();
_transaction = Session.BeginTransaction();
}
public IRepository<LogInfo> LogInfos
{
get
{
if (_logInfo == null)
{
_logInfo = new NHibernateRepository<LogInfo>(Session);
}
return _logInfo;
}
}
public void Commit()
{
if (_transaction.IsActive)
_transaction.Commit();
}
}
Unit of Work in Entity Framework 4.1
public class SqlUnitOfWork : IUnitOfWork
{
private readonly ObjectContext _context;
public SqlUnitOfWork()
{
_context = new ObjectContext(connectionString);
_context.ContextOptions.LazyLoadingEnabled = true;
}
private SqlRepository<LogInfo> _logInfo = null;
public IRepository<LogInfo> LogInfos
{
get
{
if (_logInfo == null)
{
_logInfo = new SqlRepository<LogInfo>(_context);
}
return _logInfo;
}
}
public void Commit()
{
_context.SaveChanges();
}
}
Repository using NHibernate
public class NHibernateRepository<T> : IRepository<T> where T : class, IEntity
{
protected ISession Session;
public NHibernateRepository(ISession session)
{
Session = session;
}
public IQueryable<T> FindAll()
{
return Session.Query<T>();
}
public IQueryable<T> FindWhere(Expression<Func<T, bool>> predicate)
{
return Session.Query<T>().Where<T>(predicate);
}
public T FindById(int id)
{
return Session.Get<T>(id);
}
public void Add(T newEntity)
{
Session.Save(newEntity);
}
public void Remove(T entity)
{
Session.Delete(entity);
}
}
Repository using Entity Framework
public class SqlRepository<T> : IRepository<T> where T : class, IEntity
{
protected ObjectSet<T> ObjectSet;
public SqlRepository(ObjectContext context)
{
ObjectSet = context.CreateObjectSet<T>();
}
public IQueryable<T> FindAll()
{
return ObjectSet;
}
public IQueryable<T> FindWhere(Expression<Func<T, bool>> predicate)
{
return ObjectSet.Where(predicate);
}
public T FindById(int id)
{
return ObjectSet.Single(i => i.Id == id);
}
public void Add(T newEntity)
{
ObjectSet.AddObject(newEntity);
}
public void Remove(T entity)
{
ObjectSet.DeleteObject(entity);
}
}
With this implementation I could get most of the features like saving, deleting, transaction working on both EF and NH. But when I start writing complex LINQ queries against Repositories NH fails most of the time. Some features like OrderBy and ToList throws errors when Repository is returning NhQueryable.
In the following code is called from ASP.NET MVC controller to which I'm injecting instance of IUnitOfWork using StructureMap. When NHibernateUnitOfWork is injected Where condition does not get applied where as it works as expected when SqlUnitOfWork is injected.
var query = from a in _unitOfWork.AppInfos.FindAll()
join l in _unitOfWork.LogInfos.FindAll()
on a.Id equals l.ApplicationId
where l.Level == "ERROR" || l.Level == "FATAL"
group l by new { a.Id, a.ApplicationName } into g
select new LogInfoSummaryViewModel()
{
ApplicationId = g.Key.Id,
ApplicationName = g.Key.ApplicationName,
ErrorCount = g.Where(i => i.Level == "ERROR").Count(),
FatalCount = g.Where(i => i.Level == "FATAL").Count()
};
return query.AsEnumerable();
As a side not building solution supporting different provides on top of the linq is way to disaster. Linq and IQueryable are leaky abstractions - each Linq provider can have its own "features" and limitations. Moreover EF itselfs adds some logic via custom extension methods for IQueryable (like Include or AsNoTracking in EFv4.1). These methods internally converts IQueryable to ORM specific classes.
If you want to have universal solution you must abandon Linq and add third pattern to form the abstraction. In addition to Repository and Unit of Work patterns you need custom Specification pattern. Generally you will reimplement NHibernate's Criteria API.
From an IoC point of view and a desire for elegance your way is the way to go. However, all I read about NHibernate's linq provider is that it is still "beta-ish", because it is so damn hard to write Linq providers in the first place. So it might well be that you're just running into a bug here. Currently I would be very reluctant to write production code with Linq2Nhibernate. The new QueryOver feature is much more powerful. But of course, sadly, QueryOver doesn't fit seamlessly into your architecture, because you would have to use NHibernate syntax all the way. Complex Linq queries outside your repo would be useless because they would never get translated to SQL.
I'm afraid this effectively is the kiss of death to the elegance of your design, because, to start with, it would be useless to let a repository return an IQueryable<T>. But returning IEnumerable<T> would cripple your EF implementation. So, what is boils down to, I think that for querying both implementations are too different to fit behind one neat generic interface.
Here is a very useful post on QueryOver and Linq.
BTW: this is a very interesting question and design. I wish I could give more than one vote!
In addition to technical difficulties with QueryOver mentioned by Ladislav there may be a design issue. You would not have this problem if you approach it from Domain Driven Design perspective where Repository interface is based on Ubiquitous Language and does not expose things like IQueryable which is a pure data access concept. This answer has information and links that you may find interesting.
With the introduction of .NET 3.5 and the IQueryable<T> interface, new patterns will emerge. While I have seen a number of implementations of the Specification pattern, I have not seen many other patterns using this technology. Rob Conery's Storefront application is another concrete example using IQueryable<T> which may lead to some new patterns.
What patterns have emerged from the useful IQueryable<T> interface?
It has certainly made the repository pattern much simpler to implement as well. You can essentially create a generic repository:
public class LinqToSqlRepository : IRepository
{
private readonly DataContext _context;
public LinqToSqlRepository(DataContext context)
{
_context = context;
}
public IQueryable<T> Find<T>()
{
return _dataContext.GetTable<T>(); // linq 2 sql
}
/** snip: Insert, Update etc.. **/
}
and then use it with linq:
var query = from customers in _repository.Find<Customer>()
select customers;
I like the repository-filter pattern. It allows you to separate concerns from the middle and data end tier without sacrificing performance.
Your data layer can concentrate on simple list-get-save style operations, while your middle tier can utilize extensions to IQueryable to provide more robust functionality:
Repository (Data layer):
public class ThingRepository : IThingRepository
{
public IQueryable<Thing> GetThings()
{
return from m in context.Things
select m; // Really simple!
}
}
Filter (Service layer):
public static class ServiceExtensions
{
public static IQueryable<Thing> ForUserID(this IQueryable<Thing> qry, int userID)
{
return from a in qry
where a.UserID == userID
select a;
}
}
Service:
public GetThingsForUserID(int userID)
{
return repository.GetThings().ForUserID(userID);
}
This is a simple example, but filters can be safely combined to build more complicated queries. The performance is saved because the list isn't materialized until all the filters have been built into the query.
I love it because I dislike application-specific repositories!