custom Dependency injection in a class library file c# - c#

I am working on a project(asp.net mvc-5 with jQuery) in which whole validation is happening in front-end and we are executing api's using $.ajax call, now as there are no validations on api level or not even in stored procedures of sql server, a user can easily access the the api's with wrong values, so We decided to add a logic layer in our application
so before that our structure looks like the below
jQuery -> Api layer -> Db layer
now I want to add a layer between Api layer and Db layer which will be called as Logic layer
the new structure will look like below
jQuery -> Api layer -> Logic layer -> Db layer
Note:
all the layers are different projects in same solution
Logic layer and Db layer is a class library file
Db layer is divided into 2 sub catogories (interface and class)
So we have 4 class library 1 api and 1 front end
interfaces are inherited in the class files
the class library is like below
db.Interface(class library project)
db.Class(class library project)
Logic.Interface(class library project)
Logic.Class(class library project)
We have already added dependencies for db layer the code for which looks like below,
Set of code In global.asax.cs
//Helps to find all the classes of Dblayer
string dbName = ConfigurationManager.AppSettings["DB"];
string dbDAL = Path.Combine(Server.MapPath("./DAL"), "DocPro.DMS.BusinessLayer." + dbName + ".dll");
AssemblyName an = AssemblyName.GetAssemblyName(dbDAL);
Assembly assembly = Assembly.Load(an);
Type[] assemblyTypes = assembly.GetTypes();
DALFinder.Initialize(assemblyTypes);
class file in api project called DalFinder
public static class DALFinder
{
private static List<Type> TypeList { get; set; } = new List<Type>();
public static void Initialize(Type[] typelist)
{
TypeList.Clear();
TypeList = typelist.ToList<Type>();
}
public static object GetInstance(Type plugin)
{
foreach (Type type in TypeList)
{
if (type.IsInterface || type.IsAbstract)
{
continue;
}
else
{
if (type.GetInterface(plugin.FullName) != null)
{
return Activator.CreateInstance(type, new object[] { Program.GetConnectionString() });
}
}
}
return null;
}
}
and while executing a particular function I needed to do the below in my Api layer
BusinessLayer.IAdmin.IFolderRole a = (BusinessLayer.IAdmin.IFolderRole)DALFinder.GetInstance(typeof(BusinessLayer.IAdmin.IFolderRole));
response = a.SaveFolderRole(item);
now for my current scenario I want to call db layer from my logic layer but since it is a class library file I failed to understand what should I do, for now I did something like below
public class DocTemplateController : ApiController
{
private LogicLayer.IAdmin.IDocTemplate _LogicLayer;
private BusinessLayer.IAdmin.IDocTemplate _Businesslayer;
public DocTemplateController()
{
_LogicLayer = (LogicLayer.IAdmin.IDocTemplate)BusinessLayerFinder.GetInstance(typeof(LogicLayer.IAdmin.IDocTemplate));
_Businesslayer = (BusinessLayer.IAdmin.IDocTemplate)DALFinder.GetInstance(typeof(BusinessLayer.IAdmin.IDocTemplate));
}
[HttpPost]
[Route("api/Admin/DocTemplate/GetDocTemplates")]
[Authorize]
[Filters.AuthorizeLoginApi()]
public async Task<GetTemplatesList> GetDocTemplates(DocTemplate request)
{
var response = new GetTemplatesList() { LogicLayerValidation = false };
try
{
response = _LogicLayer.GetDocTemplates(request);
if (response.LogicLayerValidation != false)
response.GetTemplates = await _Businesslayer.GetDocTemplates(request.TemplateName, request.AccountId);
}
catch (Exception ex)
{
Utils.Logger.Instance.LogException(ex);
response.LogicLayerValidation = false;
response.LogicLayerMessage = ex.Message;
}
return response;
}
}
and as I understand (I might be wrong) that this is a bad way of coding, I want to follow the structure of
jQuery -> Api layer -> Logic layer -> Db layer
how can I do this?
EDIT:
After I put bounty on the question I received lots of answers, but I
think so I needs to edit this question and provide more details, (all
the answers are good and can be very helpful for many but
unfortunately I am failed to get what I wanted)
this is how my controller looks like,
[RateLimitApi]
public class UserController : ApiController
{
private readonly LogicLayer.IAdmin.IUsers _LogicLayer;//Logic layer
private readonly LogicLayer.IGlobalValidation _CommonLogicLayer; //common logic layer
private readonly BusinessLayer.IAdmin.IUsers _Businesslayer;// business layer
private readonly BusinessLayer.IAccess.IUser _IAccessBusinesslayer;//business layer which is being used in another api
private BusinessEntities.Response.LogicLayerValidationResult _Llv; //entity for logiclayer
private SPResponse _Sp; //response entity for add/edit
private readonly ErrorLogger _Er; error log class
private readonly BusinessEntities.Response.Admin.GetUsersList _UserList; //user list
private readonly BusinessEntities.Response.Admin.GetUsersSingle _UserSingle; //single user
public UserController()
{
_LogicLayer = (LogicLayer.IAdmin.IUsers)BusinessLayerFinder.GetInstance(typeof(LogicLayer.IAdmin.IUsers));
_Businesslayer = (BusinessLayer.IAdmin.IUsers)DALFinder.GetInstance(typeof(BusinessLayer.IAdmin.IUsers));
_IAccessBusinesslayer = (BusinessLayer.IAccess.IUser)DALFinder.GetInstance(typeof(BusinessLayer.IAccess.IUser));
_CommonLogicLayer = (LogicLayer.IGlobalValidation)BusinessLayerFinder.GetInstance(typeof(LogicLayer.IGlobalValidation));
_Llv = new BusinessEntities.Response.LogicLayerValidationResult() { LogicLayerValidation = false };
_Sp = new SPResponse();
_Er = new ErrorLogger();
_UserList = new BusinessEntities.Response.Admin.GetUsersList();
_UserSingle = new BusinessEntities.Response.Admin.GetUsersSingle();
}
// GET: Admin/Users
[HttpPost]
[Authorize]
[ActionName("GetList")]
[Filters.AuthorizeLoginApi()]
public async Task<BusinessEntities.Response.Admin.GetUsersList> GetList(DocPro.DMS.BusinessEntities.Request.Admin.UsersRequest request)
{
try
{
// had to call logic layer and then call the business layer like below
_Llv = _LogicLayer.GetList(request);
if (_Llv.LogicLayerValidation)
{
_UserList.GetUsers = await _Businesslayer.GetList(request.LoginText, request.Name, request.Email, request.UserTypeId, request.IsActive, Convert.ToInt32(request.LoggedInUserId));
}
}
catch (Exception ex)
{
_Llv = _Er.LogExceptionWithLogicLayerValidations(ex, _Llv);
}
_UserList.LogicLayerValidation = _Llv;
return _UserList;
}
}

how can I do this?
is quite a general question (which is frown upon in this community).
I don't see any issue with the structure:
jQuery -> Api layer -> Logic layer -> Db layer
It is very common structure: frontend -> api-> business (logic) layer-> db
If it is a new project, I might recommend to do it with .net core and use the microsoft dependency injections or maybe use Autofac, since the topic is complex. If you really want to do it, then you can also browse their (ms or autofuc) code on github to familiarize yourself on the topic.

you should add a reference to your databaselayer project in your logic layer project. Then you can inject the db layer class in your logic layer class using dependency injection.
Then you can just call the db layer from the logic layer after you are done validating.

Why reinvent the wheel?
what you are asking for is already implemented in AspNet Boilerplate
More on this here

Related

Add caching to mvc project in data layer (class library )

i have an asp.net mvc based website, consist of three layers:
presentation layer (mvc website)
Domain layer (class library )
Data layer (class library)
and here is my code
presentation layer:
public ActionResult MyAction(int categoryId = 1)
{
var products = service.GetProductsByCategory(categoryId);
return View(products );
}
Domain Layer:
public List<MyProduct> GetProductsByCategory(int categoryId)
{
/* some code here */
return myProductDao.GetProductsByCategory(categoryId);
}
Data Layer:
public List<MyProduct> GetProductsByCategory(int categoryId)
{
/* check if data available in cache to avoid pulling database */
using (var context = new myDbEntities())
{
var myproducts = context.ProductEntities.Where(p => p.CategoryId == categoryId);
return Mapper.Map<List<ProductEntity>, List<Product>>(products);
}
}
We supposed that product table change only one time a day, and i want add a caching layer to avoid pulling database for a specific time.
problem:
i'm usually using HttpContext.Cache.Insert() in controller for caching, but now i'm planning to add caching to Data layer which it is a class library and there is no HttpContext. how usually caching done in datalayer
There are many ways to solve this. What I would do is abstract away the how to cache with an interface and inject however you want to cache into the data layer (including using HttpContext.Cache.Insert).
MyProject.Cache
public ICache
{
void Insert (string key, object value)
}
MyProject.Web
internal WebCache : ICache
{
public void Insert(string key, object value)
{
HttpContext.Cache.Insert(key, value);
}
}
public Controller
{
private service = new service(new WebCache);
}
MyProject.Domain
public Service
{
private readonly ICache _cache;
private readonly MyProductDao _myProductDao;
public Service(ICache cache;)
{
_cache = cache;
_myProductDao = new MyProductDao(_cache);
}
public List<MyProduct> GetProductsByCategory(int categoryId)
{
/* some code here */
return _myProductDao.GetProductsByCategory(categoryId);
}
}
MyProject.Data (if you just want to cache in the data layer)
public MyProductDao
{
private readonly ICache _cache;
public MyProductDao(ICache cache)
{
_cache = cache;
}
public List<MyProduct> GetProductsByCategory(int categoryId)
{
/* check if data available in cache to avoid pulling database */
_cache.DoWhatever()....
using (var context = new myDbEntities())
{
var myproducts = context.ProductEntities.Where(p => p.CategoryId == categoryId);
return Mapper.Map<List<ProductEntity>, List<Product>>(products);
}
}
Extend ICache as needed and implement it on your internal WebCache.
how usually caching done in datalayer
I don't think it should be done in the data layer.
Adding caching to the data layer seems to me like a violation of the Single Responsibility Principle. Your data layer should only be responsible for one thing - getting data from the persistent store (i.e. the database).
At some place in your code, you will need to do this workflow (or some variant of it):
Check the cache for item X.
If it is found, get the item from the cache.
If it is not found, get the item from the persistent store.
Return the item.
In my opinion, a component that is separate from the data layer should do this workflow.
Look at it this way: once you put a cache in front of your database persistence layer, you're not just getting data from the DB any more. You're getting data from this new component, and the component decides where to get the record from (cache vs. DB).

Implement data access layer best practices in .net Project MVC

I would like to improve my .NET project by adding another layer when accessing the database. This is my code:
namespace Company.Models
{
public static class AgencyBean
{
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static String createGUID(string name)
{
DataAccess dataAccess = new DataAccess();
bool exists = dataAccess.checkIfExists(Id);
if(exist)
{
dataAccess.delete(Id);
}
retur "ok";
}
}
}
I placed DataAccess class in a separate folder called "Helpers" and it contains most of my queries:
public class DataAccess
{
public bool checkIfExists(String Id)
{
try
{
SqlConnection cnn = new SqlConnection(dataConnection);
cnn.Open();
SqlCommand check_Id = new SqlCommand("SELECT COUNT(*) FROM TABLE_GUID WHERE ([USER_ID] = #Id)", cnn);
check_Id.Parameters.AddWithValue("#Id", Id);
int UserExist = (int)check_Id.ExecuteScalar();
if (UserExist > 0)
{
return true;
}
else
{
return false;
}
}
catch (SqlException ex)
{
Debug.WriteLine("SQL Exception " + ex);
DisplaySqlErrors(ex);
throw ex;
}
}
}
public class AgentBeanController : Controller
{
// GET: AgentBean
public ActionResult Index(string name)
{
return View();
}
[AllowAnonymous]
[WebMethod]
public string AgentURL() //here we create Agent URL and return it to the view
{
string var = Models.AgentBean.createGUID("TODO");
return var;
}
}
I'm accessing the database pretty much in very direct way. How would it be with a better technique, so this access can be more secure, like accessing thru a service layer?
I'm connecting to a existing sql database in some server and working with MVC architecture in my project.
So here is what I have done in the past.
First, that is your "models" namespace... models should never have database connectivity. Instead you have a seperate class, such as a controller, that hydrates some model.
Second, I've had a "service" class, which hooks up to a "repository" class. The repository class implements an interface to identify the exact "type" of database you're using.. but if that's not a part of your requirements you probably don't need to go that far.
Third, look up dependency injection (aka, DI). There are several frameworks out there. Personally I've used Autofac, but others exist as well to get the job done easier.
Fourth, on your your "controllers", "services" and "respository" classes, implement dependency injection, as well as any interfaces as needed to form a contract.
Fifth, I would use an actual controller namespace and not be working out of your models namespace to be pushing http calls band and forth.... Instead, create an action in your controller class, and instantiate an instance of your "agencyBean", hydrate it with data, and return that model out to your view.
Basically, in a scenario like this you're trying to keep each component doing what it is designated to do... breaking down responsibilities into smaller pieces and focusing on that. Your controller should just "fetch" your model and maybe do some transformations on it as needed or any other business-type logic.
Your service should handle the communication between your controller and your database layer.
Your data access layer (ie, in this case, some "repository" class...) would do all of those new data connections and/or setting up calls to stored procedures or queries.
Doing things this way has a lot of benefit. Some of the big ones are maintainability, readability, code re-use. Sure it makes your project a bit more complicated in terms of files sitting wherever... but that can be a good thing. It's so much better than slamming everything into one single class and have it do everything :)
But, just FYI, this is from an implementation I've done in the past... I'm sure there are better ways but this setup worked quite well for my team and I.
Here is a small example using some of your code you posted. I DID NOT check this for typos and it wouldn't compile, but should help give a general idea of what I'm talking about....
namespace Company.Models
{
public class AgencyBean
{
public AgencyName{get;set;}
public AgencyId{get;set;}
// other properties...
}
}
namespace Company.Controllers
{
public class MyController : Controller
{
private readonly IMyService myService;
public MyController(IMyService myService) // <-- this is your dependency injection here...
{
this.myService = myService;
}
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static String createGUID(string name)
{
var model = new AgencyBean();
model.AgencyId = 1;
model = myService.getAgency(agencyBean);
return model;
}
}
}
namespace Company.Services
{
public class MyService
{
private readonly IMyRepository myRepository;
public MyService(IMyRepository myRepository) // <-- this is your dependency injection here...
{
this.myRepository = myRepository;
}
public AgencyBean getAgency(AgencyBean model){
var dataTable = myRepository.getAgencyData(model.AgencyId);
// fill other properties of your model you have...
// ...
// ...
return model;
}
}
}
namespace Company.Repositories
{
public class MyRepository : IDatabaseCommon // <-- some interface you would use to ensure that all repo type objects get connection strings or run other necessary database-like setup methods...
{
private readonly String connectionString{get;set;}
public MyRepository()
{
this.connectionString = //get your connection string from web.config or somewhere else...;
}
public DataTable getAgencyData(int id){
var dataTable = new DataTable();
// perform data access and fill up a data table
return dataTable;
}
}
}

Unit test for my ViewModel?

I'm new to unit testing and I'm really stuck atm so I could really use some help.
Some application info
I have a WPF application in MVVM. It gets data from a database (classes generated via .edmx).
All linq queries are handled by methods in the Database class.
In CustomerListViewModel, it makes a list of all Customers to be shown in the CustomerListView.
My problem
I am new to Unit Testing. I've read about it and tried to make it work. But as I understand, it should/can be done without touching the DB. I tried to find as much info as I could, but it wouldn't work with what I have. And now I'm basically stuck.
My question
How do I unit test this piece of code? How can I know if I've successfully queried the database (with or without touching the DB in the unit test)?
(If I understand it for this piece, I can figure the rest of the classes and methods out on my own)
The code
CustomerListViewModel:
public CustomerListViewModel()
{
MyObservableCollection<Customer> listCustomers = new MyObservableCollection<Customer>();
ListCustomers = App.Database.GetCustomerList();
}
private void GetListCustomers()
{
ListCustomers = App.Database.GetCustomerList();
if (App.Database.hasError)
App.Messenger.NotifyColleagues("SetStatus", App.Database.errorMessage);
}
Database:
public MyObservableCollection<Customer> GetCustomerList()
{
hasError = false;
MyObservableCollection<Customer> customerList = new MyObservableCollection<Customer>();
try
{
QRM_Entities dc = new QRM_Entities();
var query =
from customers in dc.Customer
select customers;
foreach (Customer cust in query)
{
customerList.Add(cust);
}
}
catch (Exception ex)
{
errorMessage = "GetCustomerList() error, " + ex.Message;
hasError = true;
}
return customerList;
}
The way that you have the ViewModel currently setup will make it almost impossible to unit test.
The issue is on this line:
ListCustomers = App.Database.GetCustomerList();
I presume that App is a static and Database is the class that you are using as your Data Access Layer. So everytime that you call the constructor of your CustomerListViewModel you will call the actual Static implementation of App which you would have to setup before creating the View Model, meaning that you would always be testing with the actual Database, which is obviously what you are attempting to bypass.
In comes my favorite software principle the Dependency Inversion Principle, the premise of this is that decouple modules so that your high level module depends on an abstraction of a lower level module. And that details should depend on that abstraction. Effectively you should develop to an interface and provide this interface to dependents.
Taking your example I would extract interfaces for your database interaction and provide these to your View Model, but I'll go a step further and provide this to a model which will be provided to your view model.
IDatabase:
public interface IDatabase
{
IEnumerable<ICustomer> GetCustomerList();
}
ICustomerListModel:
public interface ICustomerListModel
{
ObservableCollection<ICustomer> Customers
{
get;
}
}
CustomerListModel
public class CustomerListModel : ICustomerListModel
{
private readonly IDatabase database;
private readonly ObservableCollection<ICustomer> customers;
public CustomerListModel(IDatabase database)
{
this.database = database;
this.customers = new ObservableCollection(database.GetCustomerList());
}
public ObservableCollection<ICustomer> Customers
{
get
{
return this.customers;
}
}
}
CustomerListViewModel
public class CustomerListViewModel
{
private readonly ICustomerListModel customerListModel;
public CusomterListViewModel(ICustomerListModel customerListModel)
{
this.customerListModel = customerListModel;
}
public ObservableCollection<ICustomer> Customers
{
get
{
return this.customerListModel.Customers;
}
}
}
So what you can see here is that I have extracted an interface for the database which I request the information from, this means that I don't care about the implementation of the IDatabase, I just now that it provides me with a collection of ICustomer's when I call GetCustomerList().
So I inject a copy of the IDatabase into the CusomterListModel class which I can then query knowing that I'll get what I want back correctly. I then inject the ICustomerListModel into the ICustomerListViewModel so that the collection can be presented to the View.
So to test the CustomerListModel I would have a test like:
[Fact]
public void Customers_IsCorrectlyInitialisedAtStartup_Test()
{
var databaseMock = new Mock<IDatabse>();
var customer = new Customer();
var customers = new [] { customer };
databaseMock.Setup(mock => mock.GetCustomerList())
.Returns(customers);
var sut = new CustomerListModel(databaseMock.Object);
Assert.Equal(customers, sut.Customers);
}
In this I have mocked a version of the IDatabase, now you can see how I don't care in the version of CustomerListModel what IDatabase I have as long as I can call GetCustomerList(). This has a setup to return a ICustomer when a call to GetCustomerList() is called. Finally I am asserting that the Customers collection was correctly populated with the returns of the IDatabase call.
Unit testing is a fine art, difficult to understand at first but when you get it working at first you'll pick it up quickly. Some things you may wish to look at to help you with generating unit testable code and actually testing:
Solid Principles, principles that every Software Engineer should at least be familiar with, will help generating code that is testable.
Dependency Injection, the wiki-page on Dependency Injection outlining the pros and cons to injecting the dependency into a constructor, when and how to use it in further examples.
Moq, a friendly and easy to use mocking framework for C#, which I used as part of my example above.

Is it bad practice to reference System.Web.Security in the model when using entity service/repository pattern?

Throughout my ASP.net site i need to check if the logged in users belongs to a role or has a field in my "UserInstance" table in my database set to true. To do this i can do the following.
if(Roles.IsUserInRole("Global Admin")
|| uow.UserInstanceService.GetUserInstance(userId,InstanceId).Admin)
{
//Do something
}
However as i am going to be using this code a lot as much of the permissions depend on the logged in user either being a "Global Admin" or a field of my table being true I don't want to write this out constantly.
One solution i have found is to create a method in the "UserInstance" Service which checks for both as seen in the "IsUserAdminOrGlobalAdmin" method.
public class UserInstanceService
{
IRepository<UserInstance> userInstanceRepository;
public UserInstanceService(IRepository<UserInstance> userInstanceRepository)
{
this.userInstanceRepository = userInstanceRepository;
}
public UserInstance GetByUserIdAndInstanceId(Guid userId, int instanceId)
{
return userInstanceRepository.GetSingle(u => u.UserId == userId && u.InstanceId == instanceId);
}
public bool IsUserAdminOrGlobalAdmin(Guid userId,int instanceId)
{
bool valid = false;
if (System.Web.Security.Roles.IsUserInRole("Global Admin"))
valid = true;
if (GetByUserIdAndInstanceId(userId, instanceId).Admin)
valid = true;
return valid;
}
//Removed rest of methods for readability
}
As this is buisness logic I put this method is in my "UserInstanceService" class which interacts with the repository class which contains the entity context. This service class resides in a seperate Model project so i had to add a reference to System.Web.Security and i am not sure if doing this is good practice. One thing i have noticed is that i can not write unit tests for this method as it relies on a user being logged in.
So my question is, is it acceptable to combine HttpContext specific functionality like the Logged in users roles, in a service?
Edit - After reading the answers I have changed my code so a Auth service (in the Web app project) is called which in turn calls the UserInstanceService to something like this.
public class Auth: IAuthService {
public bool IsUserAdminOrGlobalAdmin(Guid userId,int instanceId) {
myEntities entityContext = new myEntities
//RepsitoryBase inherits my IRepository<TEntity> class
UserInstanceService uis = new UserInstanceService(new RepositoryBase<UserInstance>(entityContext));
bool valid = false
if(Roles.IsUserInRole("Global Admin"))
valid = true;
if(uis.GetByUserIdAndInstanceId(userId,instanceId).Admin)
valid = true;
return valid;
}
}
So i could call this in my pages like this
if(Auth.IsUserAdminOrGlobalAdmin(userId,InstanceId)
{
//Do stuff
}
The original answer was written assuming the UserAccess requires the Authentication, but it appears that the Authentication consumes the UserAccess; simply invert the dependencies, but everything else should be usable in about the same manner.
Original answer:
Pull the ASP.NET-specific code into it's own service separate from the repository. Then that service - say, the Auth Service - can be used by any component (such as the UserInstanceService) that needs access to centralized authentication/authorization logic.
Consume the Auth as a dependency per IoC principles, hopefully using some DI to make life easier.
If the Auth service is kept separate it can also be trivially mocked for testing, such as testing what happens when the use is authenticated or not, which entirely avoids the need to setup a full ASP.NET stack for the User service.
In addition, because services (interfaces) and components (classes) are separate, the actualy HTTP-utilizing component can live in a separate project from the service and wired in later - this will avoid pulling in Web dependencies to the Model project.
For example,
// This is the Service Contract and can live in the Model
public class IAuthService {
void AssertCurrentUserIsAdminOrGlobalAdmin();
void AssertIsUserAdminOrGlobalAdmin(Guid userId,int instanceId);
}
// This is the Component, which provides the Service, and is part
// of the Web/HTTP-specific project. It is wired up via IoC/DI from
// the large context of the application.
public class Auth: IAuthService {
public void AssertCurrentUserIsAdminOrGlobalAdmin() {
// This one already knows the applicable HTTP/User Context
}
public void AssertIsUserAdminOrGlobalAdmin(Guid userId,int instanceId) {
// Do whatever
}
}
// This Component is part of the Model
public class UserInstanceService
{
// IoC dependencies
IRepository<UserInstance> userInstanceRepository;
IAuthService authService;
}
You could set the current principal on the thread and use that instead. I think thats most of what ASP.Net does for you as well.

Using Fluent NHibernate with a Data Access Layer

First a little background: I have a solution with the following 3 projects in it:
MVC Project (User facing website)
API Project (business logic project)
Data Access Project (project where NHibernate lives)
I have the Fluent mappings in the DA layer, and (for now) I build the Hibernate SessionFactory in the GLobal.asax of the MVC site. This is not ideal as I want to have NHibernate completely contained in the DA layer and have the MVC app only communicate with the API layer. Also, I want to build the SessionFactory only once as it is an expensive operation.
To make things more complicated I have an inheritance structure like so:
User object in API layer inherits from
User data object in DA layer inherits from
Data object in DA layer.
Data object is responsible for saving the object to the database as the saving function is the same across all objects and I do not want to repeat code. The problem I am having is how do I save the User object to the database from inside the Data object class while using a SessionFactory that I instantiated when the user logged into the website and can persist through out their session.
If anything is not explained clearly please let me know.
One way to do that would be using the DI pattern, with e.g. Unity.
Implement your data object having a constructor which takes for example an IRepository interface. The implementation of this interface handles the nHibernate session factory...
Your data object could also be generic where T is one for example User data object. Then you implement a methods in data object to e.g. save, update, delete T with the injected IRepository
pseudo code for a data object
public interface IEntity
{
}
public interface IRepository
{
ISession Session { get; }
}
public class DataObjectBase<T> where T : IEntity
{
private IRepository Repository { get; set; }
public DataObjectBase(IRepository repository)
{
this.Repository = repository;
}
public T Get(int id)
{
return Repository.Session.Get<T>(id);
}
public void Save(T value)
{
Repository.Session.Save(value);
}
public void Update(T value)
{
Repository.Session.Update(value);
}
public void Delete(T value)
{
Repository.Session.Delete(value);
}
public IQueryable<T> Query()
{
return Repository.Session.Query<T>();
}
}
Implementation of your specific data object
public class ADataObject : IEntity
{
public int Id { get; set; }
// [...]
}
Implementation of your data context for the data object
public class ADataObjectContext : DataObjectBase<ADataObject>
{
public ADataObjectContext(IRepository repository)
: base(repository)
{
}
}
A simple example test using Unity
public class Test
{
public void Run()
{
IUnityContainer myContainer = new UnityContainer();
myContainer.RegisterType<IRepository, NHibernateRepository>();
var ctx = myContainer.Resolve<ADataObjectContext>();
var obj = ctx.Query().Where(p => p.Id == 2);
}
}
Of cause you would have to implement the NHibernateRespository to do whatever you want it to.
The UnityContainer initialization should be done within your global.asax within the MVC project. You can also configure Unity via web.config.
The NHibernateRespository should actually be a singleton. This can either be implemented by you, or you simply use the Unity functionality to instantiate your type as singleton. The new ContainerControlledLifetimeManager() does exactly that.
Instead of exposing the session as a property you can of cause expose a method which opens a new session. Or you implement a Begin and End unit of work, which is common practice in web environments...
Other links for a normal repository pattern, and unit of work, unity... or simply search on Google for nhibernate repository pattern
http://slynetblog.blogspot.de/2011/11/in-spite-of-common-now-approach-of.html
http://blog.bobcravens.com/2010/07/using-nhibernate-in-asp-net-mvc/
http://msdn.microsoft.com/en-us/library/dd203101.aspx
You can use this options:
Using AOP: when a function is called in API layer, AOP creates a session and passes the value parameters in methods or constructors to DA layer.
From MVC project to DA layer, it passes a session to DA layer with parameters in method o constructors, through all the layers.
Thinks the session is always associated with the interface layer.

Categories