Recently learned some knowledge about asp.net mvc, so to take a small project to practice practicing, improve their own code ability and thinking ability. Before that, it was easy to do something, directly using the soft that generated code to generate a simple three-tier architecture as the overall framework of the project, The database access layer is ado.net. It's a lot of trouble to do that, if you want to change the database for the project, add a table to the database or add a field to the table, or do not use the Ado.net to access the database with an ORM framework, etc. In order to solve these problems we need to rethink how to build.
about the database access layer
Database access drive Layer--everyone knows that ef,nh with ado.net or your own implementation, these are for us to access the database or database operations to establish a bridge, of course, the database may also be different databases, these are based on the requirements of the project, As for the choice, it depends on the situation. I used the ef--model-first here. I am directly inside the EDMX design model, and then generate entities and databases, specifically as follows, made a simple authority management (not fully implemented).
Copy Code code as follows:
public class Baserepository<t>:idal. ibaserepository<t> where T:class
{
Private DbContext container = Efcontentfactory.getcurrentcontext ();
#region Increase
Public T addentity (t entity)
{
Container. Set<t> (). ADD (entity);
return entity;
}
#endregion
#region Delete
public bool Deleteentity (T entity)
{
Container. Set<t> (). Attach (entity);
Container. Entry (entity). state = entitystate.deleted;
return true;
}
#endregion
#region Modifications
public bool Updateentity (T entity)
{
Container. Set<t> (). Attach (entity);
Container. Entry (entity). state = entitystate.modified;
return true;
}
#endregion
#region Query
Public iqueryable<t> getentities (func<t, bool> lambdawhere)
{
iqueryable<t> entities = container. Set<t> (). Where (Lambdawhere). AsQueryable ();
return entities;
}
#endregion
#region Paging
Public iqueryable<t> getentitiesbypageindex<ts> (int pageIndex, int pageSize, out int totalcount, func<t, Bool> Lambdawhere, Func<t, ts> orderbyrole, bool descending)
{
var temp = container. Set<t> (). Where (Lambdawhere). AsQueryable ();
TotalCount = temp. Count ();
if (descending)
{
temp = temp. OrderByDescending (Orderbyrole)
. Skip (PageSize * (pageIndex-1))
. Take (pageSize). AsQueryable ();
}
Else
{
temp = temp. by (Orderbyrole)
. Skip (PageSize * (pageIndex-1))
. Take (pageSize). AsQueryable ();
}
return temp;
}
#endregion
}
At this point I thought I had finished writing my database access layer, then you can write business logic layer of things, but in fact, think about it, if you want to change the database, or change to EF or ado.net if the old, the whole project of each layer need to replace, greatly increased the workload, Here we can do a hand and foot, the data access layer to the abstraction of a layer, which requires the interface.
Idal. Ibaserepository<t> basically think about our BLL layer if we don't have an interface, we write Dal.xxrepository=new xxrepository (), and the old way, as I said before, Maintainability substitution is greatly reduced. We can write that now.
Idal.xxrepository=new xxrepository (). So when we replace the DAL layer, the BLL layer doesn't need to care how you actually do it. This is very important. An interface is equivalent to a contract that constrains what functionality you have to implement, If we want to add functionality can be added directly to the interface, the interface needs to be part of the interface, as I give the above code, the base class needs an interface, the subclass also needs. So we abstract out a database interface layer.
Abstract factory and simple factory
We can also abstract the business layer and the database access layer again, we need to use the factory--it's very simple, the class of Dal layer from the factory class and return the Idal interface.
Copy Code code as follows:
public static Class Shopdaofactory
{
public static Iuserinforepository Userinforepository
{
Get{return new Userinforepository ();}
}
public static Irolerepository Rolerepository
{
Get{return new Rolerepository ();}
}
}
Then the business layer to get the interface does not need to care about how to achieve, this is a layer of abstraction, of course, you can also use abstract factory, using reflection and configuration plus cache to achieve, but in general, simple factory enough, here is equivalent to a database access layer entrance.
base class and subclass of business logic layer
When we have a lot of physical models, if we don't have a base class, to write a bunch of repetitive things, we are now going to put these repetitive things into the base class for us to implement, like the DAL layer, we define a base class, but at the BLL layer we will encounter a problem, Idal. Ibaserepository<t> how to get the interface from the factory ... Think about ..... Our subclasses can know the interface we need------we can do something, let the parent class be an abstract class, define an abstract method, and then let the subclass rewrite the method and call it in the constructor, because we have to use this interface, so we have to do it in the constructor
Copy Code code as follows:
Public abstract class Baseservice<t>: Ibll. ibaseservice<t> where T:class, new ()
{
Public Baseservice ()
{
GetInstance ();
}
Protected Idal. Idbsession _dbsession = Dbseesionfactory.getsession ();
Protected Idal. Ibaserepository<t> currentrepository {get; set;}
public abstract void getinstance ();
Public iqueryable<t> getentities (func<t, bool> lambdawhere)
{
_dbsession.savachanges ();
Return currentrepository.getentities (Lambdawhere);
}
public bool Deleteentity (T entity)
{
Currentrepository.deleteentity (entity);
return _dbsession.savechanges () > 0;
}
public bool Updateentity (T entity)
{
Currentrepository.updateentity (entity);
return _dbsession.savechanges () > 0;
}
Public T addentity (t entity)
{
var en = currentrepository.addentity (entity);
_dbsession.savechanges ();
Return en;
}
Public iqueryable<t> getentitiesbypageindex<ts> (int pageIndex, int pageSize, out int totalcount, func<t, Bool> Lambdawhere, Func<t, ts> orderbyrole, bool descending)
{
Return Currentrepository.getentitiesbypageindex (PageIndex, pageSize, out TotalCount, Lambdawhere, Orderbyrole,
Descending);
}
}
}
Other business layers also need to be abstracted out of the interface as a constraint so that the UI layer does not need to care how your business layer is implemented ...
Another test dbsession to implement database entry
Let's look at a class that has attributes in it, dbsession for interfaces, corresponding implementation classes for the interface, two methods SaveChanges (), and Exesql (EF 5.0+), which returns the SaveChange () of the current EF thread class context. And the return value of executing the SQL statement, how can you ensure that the EF context in the current process is only one, and we look at another class.
Copy Code code as follows:
public partial class Dbsession:idal. Idbsession
{
#region Code generator Generation
Public Idal. Irolerepository rolerepository
//{
get {return new rolerepository ();}
//}
Public Idal. Iuserinforepository userinforepository
//{
get {return new userinforepository ();}
//}
#endregion
public int SaveChanges ()
{
Return Efcontentfactory.getcurrentcontext (). SaveChanges ();
}
public int Excutesql (string strSQL, system.data.objects.objectparameter[] parameters)
{
Return Efcontentfactory.getcurrentcontext (). Database.executesqlcommand (strSQL, parameters);
}
}
public class Efcontentfactory
{
public static DbContext Getcurrentcontext ()
{
DbContext obj = callcontext.getdata ("DbContext") as DbContext;
if (obj==null)
{
obj = new Model.datacontainer ();
Callcontext.setdata ("DbContext", obj);
}
return obj;
}
}
CallContext is a private collection object similar to the thread-local storage of method invocations and provides a data slot unique to each logical thread of execution. The data slot is not shared between the invocation contexts on other logical threads, a phrase that is intercepted from MSDN, and there are several ways in which we use SetData and GetData to ensure that the context thread is unique, and the same we let him interface with the factory implementation
Copy Code code as follows:
public class Dbseesionfactory
{
<summary>
Guarantee Line Agenda dbsession unique
</summary>
<returns></returns>
public static Idal. Idbsession getsession ()
{
Idal. Idbsession _dbsession = CallContext.GetData ("Dbsession") as idbsession;
if (_dbsession = null)
{
_dbsession = new Dbsession ();
Callcontext.setdata ("Dbsession", _dbsession);
}
return _dbsession;
}
}
This is done when subclasses of the business layer override methods, and the same base class adds: protected Idal. Idbsession _dbsession = Dbseesionfactory.getsession ();
Copy Code code as follows:
public partial class ACTIONINFOSERVICE:BASESERVICE<ACTIONINFO>,IBLL. Iactioninfoservice
{
public override void GetInstance ()
{
Currentrepository = _dbsession.actioninforepository;
}
}
public partial class R_USERINFO_ACTIONINFOSERVICE:BASESERVICE<R_USERINFO_ACTIONINFO>,IBLL. Ir_userinfo_actioninfoservice
{
public override void GetInstance ()
{
Currentrepository = _dbsession.r_userinfo_actioninforepository;
}
}
public partial class ROLESERVICE:BASESERVICE<ROLE>,IBLL. Iroleservice
{
public override void GetInstance ()
{
Currentrepository = _dbsession.rolerepository;
}
}
Why did you do that? When we use the EF, such as a method inside to operate a number of tables, and constantly need to use the context, which can help us to have a lot of things in the end directly to a _dbsession.savechange (). Can achieve bulk delete modification and so on. Look at me specifically, I did a lot of deletion today.
Copy Code code as follows:
public int deleteusers (list<int> List)
{
foreach (var i in list)
{
_dbsession.userinforepository.deleteentity (New UserInfo () {ID = i});
}
return _dbsession.savechanges ();
}
Good sleepy, the last few days to learn things summed up under or harvest a lot, although there are some things are not very understanding, take a look to understand, and share to the university to study together ~