NoSQL Recent momentum is good, http://www.aliyun.com/zixun/aggregation/13461.html ">mongodb is one of the Jiao jiao, oneself learn nosql when also reference a lot of information, The final decision to start with MongoDB, the most important reason has two points: 1 oneself is the simple amateur, all problems I am thinking whether has the simple method solution, would rather stop to think a lot of time, also do not want to use the stupid method to do immediately, and the MongoDB operation is very simple, 2 oneself is JS's amateur, Nothing is like to take a JS to see from the beginning to the end, also no matter how much to remember, also regardless of the use do not have to get, is like, MongoDB to Bson format storage, so the operation also up also calculate handy! Now do a project is using MongoDB as a database, a DAL,BLL directly access to the database, and then to the UI, and BLL is completely static (I like the static method of the call simple, but malicious static class can not inherit!) , at that time to consider the use of MongoDB drive to operate too straightforward! Feel no need to write a dal!, then know my idea is still very naïve, haha! Here's how to do it now
One, module layer
[Serializable]
public sealed class User
{
public ObjectId ID;
public string N;
public int age;
public Birthday birth;
public sealed class Birthday
{
public int y;
public int m;
public int D;
}
}
At first glance, there are a few places are not standard, 1 class name first letter and public fields do not have uppercase, 2 exposed fields, instead of using Attributes, 3 field naming does not express its meaning. Now explain one by one, the class name and the field is not capitalized first letter is the name of the database is followed by JS, with JS, you will generally write:
var user={id:objectid ("123456"), N: "Loogn", Age:23,birth:{y:1989,m:7,d:7}}
However, some people may say that can be associated with MongoDB.Bson.Serialization.Attributes.BsonElement such an attribute! But I won't do that because it's too much trouble! There may still be a question, stay to 3rd.
Exposing fields without using attributes is also unreasonable, school teachers have handed, whether you can understand, anyway is to privatize the field, want to public please use properties, haha! But I think for a long time or not to go the usual way, so far with the field has not been a defect problem, I do not guarantee that the future will not, but I feel very small, even if there are any problems need to use attributes, followed by {get;set;} No trouble! After all, the attribute is still the method, with the attribute has superfluous method call overhead, and entity class is an unusual class, generally only represents the object state (with the field), attribute if there is logic (as the teacher often said the age can not be less than 0 and not more than 150 and so on!) Will you put it here? You're obviously doing it in BLL! The field name is too short to express its meaning, in fact this can be with the first one, MongoDB is modeless, the same collection can protect multiple irregular documents, such as the user set:
{id:1,n: "user1", desc: "My description"}
{id:2,n: "User2"}
So the database must save the name of each element of the document (that is, id,name,desc,id,name), so the shorter the element name is more space-saving, originally used to express the name, here with N, in fact, as long as the common agreement, most people are acceptable.
There's a built-in class birthday in the user, and this class caps the first letter, I think so, the embedded class names are all in the C # naming convention, because the container class has a field of that embedded class type, this is birth, but if you can't find the right abbreviation, you can do it directly in the lowercase inline class name. such as the embedded city, the field name is not repeated.
Two, the DAL layer
In this layer to write a base class, the completion of this base class, the other various DAL classes are clouds ~, before writing the base class has a mongohelper,mongohelper is very simple, directly give the code and do not write an explanation:
Mongoserver
After you can write Basedal, if there is no generics, the DAL work is really uninteresting, but now the work of the generic dal is much more interesting, the first bearing code:
<summary>
Data Access layer base class
</summary>
<typeparam name= "T" > Document entity Class </typeparam>
Public abstract class Basedal<tdocument>
{
Protected internal string CollectionName {set; get;}
<summary>
Set the name of the collection
</summary>
protected abstract string setcollectionname ();
Private mongocollection<tdocument> m_collection;
<summary>
Get Mongocollection Object According to CollectionName
</summary>
protected internal mongocollection<tdocument> Collection
{
Get
{
if (m_collection = null)
{
CollectionName = Setcollectionname ();
M_collection = Mongohelper.getdatabase (). Getcollection<tdocument> (CollectionName);
}
return m_collection;
}
}
<summary>
Get a Document object based on query criteria
</summary>
<param name= "Query" > Criteria </param>
<param name= "Preprocess" > Pretreatment method </param>
<returns></returns>
Public tdocument FindOne (imongoquery query, preprocesshandler<tdocument> preprocess)
{
var document = Collection.findone (query);
if (preprocess!= null)
{
Preprocess (ref document);
}
return document;
}
<summary>
Convert Mongocursor to IList type
</summary>
<param name= "cursor" > Document Cursors </param>
<param name= "Preprocess" > Pretreatment method </param>
<returns></returns>
protected internal ilist<tdocument> cursortolist (mongocursor<tdocument> cursor, preprocesshandler< Tdocument> preprocess)
{
ilist<tdocument> list = new list<tdocument> (30);
BOOL ispreprocess = preprocess!= null;
foreach (tdocument document in cursor)
{
var doc = document;
if (ispreprocess)
Preprocess (ref doc);
List. ADD (DOC);
}
return list;
}
<summary>
Query a collection based on queries
</summary>
<param name= "Query" > Conditions </param>
<param name= "Preprocess" > Pretreatment method </param>
<returns></returns>
Public ilist<tdocument> Find (imongoquery query, Mongocursorsettings cursorsettings, preprocesshandler< Tdocument> preprocess)
{
var cursor = collection.find (query);
if (cursorsettings!= null)
{
Cursorsettings.set (cursor);
}
var list = cursortolist (cursor, preprocess);
return list;
}
}
The top code is the set of the operation of which set, here is a bit uncomfortable, why the property Get and set can not be abstract?! Although you can mark the entire attribute as abstract, but you also write the implementation of get and set in the implementation class (set can be an empty block of code), so here we return to a Setcollectionname abstract method for subclasses to set their own corresponding set names.
When you get Mongocollection objects, especially mongocollection<tdocument> such strong type objects, basedal the rest of the work has become a cloud! (both encapsulation and personalization of drive methods), such as the FindOne method, use a delegate:
public delegate void Preprocesshandler<t> (ref T document);
There are many such cases, to get an entity always have to first deal with the UI is easy to use, such as the user head is empty, to a default, Preprocesshandler is to BLL processing leave a convenient interface!
Here select delegates instead of other elements to make the program more flexible (with anonymous delegate, I like it!), we notice that the entity class is passed by reference, in fact there is a pit, I jumped in, but climbed up! Then there is a card: "Here is a hole, please take a detour," so as not to rush you also planted a somersault.
There is a situation where if you put a null entity object into the processing method, and in the processing method to judge if it is null to manifest, this is not the expected effect, this null is not the NULL, the entity after the method of the parameter is to point to the new object, but the pass over the argument or point to null? This is not what we want, with ref can be solved, you may say that you can return the entity object, yes, but the individual does not like that way of writing, so the final processing method to write Reurn code, call the method may also have to write code to receive, Trouble!
FindOne example is over, but FindOne is far from finished, you can do all kinds of overloads you like.
See Find to get more than one document method, here I choose ilist< entity > as return value, in BLL never to operate mongocursor, but there is such a problem, set fields, Limit, sorting, etc. are in the mongocursor operation Ah, And these operations are probably all passed from the UI, so here's a mongocursorsettings class that encapsulates these settings:
Mongocursorsettings
Code without explanation, you can extend this class for more settings without modifying the Find method.
Cursortolist method is also very simple, in fact, the Preprocesshandler written in the DAL layer is the reason for this method, cautious you must have found the Preprocesshandler write in the BLL more reasonable, but then the collection of documents will be traversed more than once, Mongocursor to IList again, Preprocesshandler deal IList again! Alas, the programmer is easy ~ ~ ~
Of course, you can also do all sorts of things you like to find the overload, more to write other aspects (Insert,update,remove ...) method to improve the Basedal class.
Finally let the pro look at the user cloud (other clouds are also this kind of):
public class User:basedal<user>
{
protected override string Setcollectionname ()
{
return "user";
}
}
Iii. BLL Layer
There are generics that mean, see BASEBLL:
<summary>
Business Logic Layer base class
</summary>
<typeparam name= "Tdal" > Data access Type </typeparam>
<typeparam name= "Tdocument" > Document model Type </typeparam>
Public abstract class Basebll<tdal, tdocument> where Tdal:dal. Basedal<tdocument>,new ()
{