Preface:
PreviousArticleThis article describes some theory of implementing the Dal. It is a preliminary attempt of implementing the Dal.
The main topics in this article are as follows:
1) basic design of the dal
2) further thoughts on basic operations
3) thoughts on querying objects
1. Design Basic Dal operations
Richard believes that it is important to design an architecture or framework:
A. Overall Ability to grasp.
B. Abstract capabilities.
C. analysis capability
First, in general, Richard thinks that the most basic and easiest way to think of dal is CRUD (create, read, update, delete.
So Richard wrote the name of the basic operation on the grass paper:
Addsingledataentity;
Adddataentitylist;
Updatesingledataentity;
Updatedataentitylist;
Deletesingledataentity;
Deletedataentitylist;
Getsingledataentiry;
Getdataentitylist;
The method name listed above is very long. In fact, Richard also referred to it when thinking about the names of these methods. some suggestions in the net design specification: The method name should be "self-explanatory, because the architecture design is still used by developers at the end, so the definition of the method should be clear at a glance what it does, standard naming can also greatly reduce maintenance costs. (These names may be a bit difficult to name, but will be reconstructed later)
Starting from the general perspective, we have defined basic operations. Now, we will begin to analyze and implement these methods step by step.
Richard began to think about the implementation of the first method. In fact, Richard knew in his mind that it may be important to consider which method is the first one, however, we should start with at least one question before we know everything clearly. As we think deeply, many problems will gradually emerge, and everything will become clearer at that time.
For the addsingledataentity method, you must first consider what to add to this methodDatabaseIn, that is to say, we need to consider the parameters of this method, and this parameter must be "compatible", because previously Richard was trying to design a dal that would remain unchanged. Before considering this parameter, Richard knows exactly how to access. NET data.TechnologyMedium, the orm technology, such as LINQ and Entity Framework, has been widely used. Therefore, we should fully consider some existing technologies when designing the Dal (try to avoid re-building the wheel ).
In addition, how the data is stored in the database and how the data is retrieved from the database can be completely handed over to the Orm. The final result is: in the Dal, only the ing entities that operate these ORM are involved. Based on this idea, Richard determined that the addsingledataentity parameter is a data entity. (In this series of articles, the data entity, that is, dataentity, is the one-to-one correspondence between the entities produced by the orm ing a database table and the tables in the database. For example, there is an employee table in the database, LINQ to SQL maps it to a class of employee, which is called a data entity ). Because these methods ultimately operate on data entities, the interface names containing these methods are defined as idatacontext.
Because different tables generate different data entities, but Richard also wants the addsingledataentity method to accept any data entities, it is necessary to abstract the data entities at this time. So Richard thought of defining an interface: idataentity, which is intended to inherit all data entities generated through Orm. Richard also thought:
1. If BLL directly references the Dal, idataentity may appear in BLL.
2. if BLL uses repository to retrieve data from the Dal, BLL may not directly reference the dal at that time, but BLL still needs to use data to do things, so idataentity will still appear in BLL, therefore, the idataentity interface is best defined in a public place.
Richard decided to create a common class library and add the definition of the idataentity interface. Now there is nothing in this interface, just a tag, indicating that the class inheriting this interface is the data entity class.
Addsingledataentity (idataentity dataentity );
Another point is to try to use the type security method, so Richard changed the method to the model method:
Addsingledataentityt (T dataentity) where T: idataentity, class, new ();
T constraints: T: idataentity, class, new () take into account some of the requirements of data entities in LINQ and EF.
In general, the add method returns whether the add operation is successful, true or false. The method is modified again:
Bool addsingledataentityt (T dataentity) where T: idataentity, class, new ();
Then Richard wrote the definitions of some of the methods listed above:
Bool addsingledataentityt (T dataentity) where T: Class, idataentity, new ();
Bool adddataentitylistt (listt dataentitylist) where T: Class, idataentity, new ();
Bool deletedataentitylistt (listt dataentitylist) where T: Class, idataentity, new ();
Bool deletesingledataentityt (T dataentity) where T: Class, idataentity, new ();
Bool updatesingledataentityt (T dataentity) where T: Class, idataentity, new ();
Bool updatedataentitylistt (listt dataentitylist) where T: Class, idataentity, new ();
As for getdataentitylist, follow the previous query object idea to pass in an IQUERY interface:
Listt getdataentitylistt (IQUERY query) where T: Class, idataentity, new ();
2. Further Thoughts on basic operations
Indeed, there are no problems with the above basic operations. Now Richard has considered some other problems, or take the addsingledataentity method as an example:
A. Sometimes, you not only need to know whether the inserted data is successful, but also want to return the primary key information of the newly added data in the database for other purposes. What should I do? Query again?
B. If the insertion fails, will the system only return a false value? Other Call modules may want to know what exceptions have caused insertion failure, and other modules have their own solutions for exceptions, therefore, addsingledataentity must provide sufficient information.
Based on the above thinking, this basic operation method cannot simply return some simple values. That is to say, these methods need to return a packet: it contains a lot of information so that other call modules can use this information. It feels like eventargs in the C # event.
Therefore, Richard adds an object to the common class library, which is defined as follows:
Code
Public Class Dataresult T Where T: idataentity
{
Public List T Entitylist { Get ; Set ;}
Public Bool Issuccess { Get ; Set ;}
Public Exception exception { Get ; Set ;}
Public Object Customdata { Get ; Set ;}
}
This class will return results as a method.
Richard found that the above method is indeed self explanatory, but many developers are familiar with the names of these crud operations, in addition, the users of the final developed architecture are developers, which should be in line with their habits. Therefore, Richard changed the method name. The changed version is as follows:
Code
Public Interface Idatacontext
{
Ilist T Query T (IQUERY querycondition) Where T: Class , Idataentity, New ();
Ilist T Query T (IQUERY querycondition, Int Pageindex, Int Pagecount) Where T: Class , Idataentity, New ();
// Crud services (well, mostly CUD)
T add T (T item) Where T: Class , Idataentity, New ();
Ilist T Add T (List T Itemlist) Where T: Class , Idataentity, New ();
Bool Delete T (List T Itemlist) Where T: Class , Idataentity, New ();
Bool Delete T (T item) Where T: Class , Idataentity, New ();
T update T (T item) Where T: Class , Idataentity, New ();
List T Update T (List T Itemlist) Where T: Class , Idataentity, New ();
}
3. Some Thoughts on querying objects
In the above basic operations, the query object is input in the query method, because the query object is based on the interpreter and can be cached after the query object is interpreted. In the future, if the two query objects are the same (for example, when constructing a query object, you can define a unique identifier for it), you do not need to explain the query object any more. If the data found based on the query object is read-only, it is better to cache the query object and corresponding results.