Before next chapter's deep dive into a real ASP. net mvc e-commerce development experience, it's important to make sure you're re familiar withArchitecture,Design Patterns, tools, and techniquesThat we'll be using. By the end of this chapter, you'll know about the following:
- MVC Architecture
- Domain Models and Service Classes
- Creating loosely coupled systems using a dependency injection (DI) Container
- The basics of Automatic Testing
- C #3 language features that all ASP. net mvc developers need to understand
§ 3. 1 Understanding MVC Architecture
Your application will be split into (at least) three distinct pieces:
§ 3. 1.1 The Smart UI (Anti-pattern)
Ignore
§ 3. 1.2 separating out the domain model
Model-View Architecture
Architecture as shown:
§ 3. 1.3 three-tier architecture
Architecture as shown:
§ 3. 1.4 MVC Architecture
Architecture as shown:
Implementation in ASP. NET MVC
Nothing interesting
History and Benefits
ASP. net mvc is hardly the first web platform to adopt MVC Architecture.Ruby on RailsIs the most famous MVC poster child, but ApacheStruts,Spring MVC, And export others have already proven its benefits.
§ 3. 1.5 variations on MVC
Where's the data access code?
Putting domain logic directly into Controllers
Model-View-presenter
Model-View-view Model
§ 3. 2 Domain Modeling
Take the real-world objects, processes, and rules from your software's subject matter and encapsulate them in a component calledDomain model.This componentIs extremly importantTo your software. Everything else, includingControllersAndViews, Is just a technical detail designedSupport or permitInteraction with the domain model.
The part of the software that specifically solves problems from the domain model usually constitutes only a small portion of the entire software system, although its importance is disproportionate to its size. to apply our best thinking, we need to be Able to look at the elements of the model and see them as a system. we must not be forced to pick them out of a much larger mix of objects, like trying to identify constellations in the night sky. we need to decouple the domain objects from other functions of the system, so we can avoid confusing domain concepts with concepts related only to software technology or losing sight of the domain altogether in the mass of the system. Domain Driven Design : Tackling complexity in the heart of software, By Eric Evans (Addison-Wesley, 2004) |
§ 3. 2.1 An example Domain Model
Let us talk an online auctions site, you might get started with something as follows:
This distriindicates that the model contains a set of members who each hold a set of bids, and each bid is for an item. An item can have multiple bids from different members.
§ 3. 2.2 ubiquitous language
A key benefit of implementing your domain model as a distinct component is the ability to design it according to the language and terminology of your choice.
§ 3. 2.3 aggregates and Simplification
A c # representation of our domain model so far looks like this:
Public class member {Public String loginname {Get; set;} // the unique key public int reputationpoint {Get; Set ;}} public class item {public int Itemid {Get; private set;} // the unique key public String title {Get; set;} Public String description {Get; set;} public datetime auctionenddate {Get; set ;} public ilist <bid> bids {Get; private set ;}} public class bid {Public Member member {Get; private set ;} public datetime dateplaced {Get; private set ;} public decimal bidamount {Get; private set ;}}
§ 3. 2.4 keeping data access code in repositories
Sooner or later you'll have to think about getting yourDomain objectsInto and out of some kindPersistent Storage-Usually a relational, object, or document database. persistence is an independent concern, so you don't want to mix persistence code with domain model code, either by embedding Database Access Code directly into domain entity methods, or by putting loading or querying code into static methods on those same classes.
The usual way to keep this separation clean is to defineRepositories. When you're working with aggregates, it's normal to defineA separate repository for each aggregate, Because aggregates are the natural unit for persistence logic. For example, continuing the auctions example, you might start with the following two repositories:
public class membersrepository {public void addmember (member) {/* implement me */} Public Member fetchbyloginname (string loginname) {return new member ();/* implement me */} public void submitchanges () {/* implement me */} public class itemsrepository {public void additem (item) {/* implement me */} public item fetchbyid (INT Itemid) {return new item ();/* implement me */} public ilist
listitems (INT pagesize, int pageindex) {return new item [] {new item ()}; /* implement me */} public void submitchanges () {/* implement me */}
Notice that repositories are concerned onlyLoading and saving data, And contain as little domain logic as is possible. In this example, you'll see how to useORM tool(LINQ to SQL) to make your job easier.
§ 3. 2.5 using LINQ to SQL
It is an ORM tool, not as mature and sophisticated as alternatives suchNhib.pdf, But sometimes easier to use, considering its full support for LINQ and its release sion by default in all editions of Visual Studio 2008 and 2010.
DatacontextIs your entry point to the wholeLINQ to SQL API. It knows how to load, save, and query for any. Net type that has LINQ to SQL mappings. After it loads an object from the database, itKeeps track of any changesYou make to that object's properties, so it can write those changes back to the database when you call its submitchanges () method. it's lightweight (I. E ., inexpensive to construct); it can manage its own database connectivity, opening and closing connections as needed; and it doesn't even require you to remember to close or dispose of it. |
There are variousDifferent ways to use LINQ to SQL. Here are the two main ones:
- you can take a database-first approach by first creating a SQL Server database schema. then, as I just described, use LINQ to SQL's visual designer to have it generate corresponding C # classes and a mapping configuration.
- you can take a code-first approach by first creating a clean, object-oriented domain model with interfaces for its repositories. then create a SQL server
database schema to match. finally, either provide an XML mapping configuration or use mapping attributes to tell LINQ to SQL how to convert between the two. (Alternatively, just give LINQ to SQL the mapping configuration and ask it to create the initial SQL Server database for you .)
You can keep persistence concerns separate from the domain classes, and you get total control over how they are structured and how their properties are encapsulated. plus, you can freely update either the object-oriented or relational representation and update your mapping configuration to match.
Implementing the auctions Domain Model
With LINQ to SQL, you can set up mappings between C # classes and an implied database schema either by decorating the classesSpecial attributesOr by writingXml configuration file. Let us use attributes here.
Using system; using system. collections. generic; using system. LINQ; using system. web; using system. data. LINQ; using system. data. LINQ. mapping; namespace mvcprogram. models {[Table (name = "members")] public class member {[column (isprimarykey = true, isdbgenerated = true, autosync = autosync. oninsert)] internal int memberid {Get; set;} [column] Public String loginname {Get; set;} [column] public int reputationpoint {Get; set ;}} [Table (name = "items")] public class item {[column (isprimarykey = true, isdbgenerated = true, autosync = autosync. oninsert)] public int Itemid {Get; internal set;} [column] Public String title {Get; set;} [column] Public String description {Get; set ;} [column] public datetime auctionenddate {Get; set;} [Association (otherkey = "Itemid")] private entityset <bid> _ bids = new entityset <bid> (); public ilist <bid> bids {get {return _ bids. tolist (). asreadonly () ;}} [Table (name = "bids")] public class bid {[column (isprimarykey = true, isdbgenerated = true, autosync = autosync. oninsert)] internal int bidid {Get; set;} [column] internal int Itemid {Get; set;} [column] public datetime dateplaced {Get; internal set ;} [column] public decimal bidamount {Get; internal set;} [column] internal int memberid {Get; set;} internal entityref <member> _ member; [Association (thiskey = "memberid", storage = "_ member")] Public Member member {get {return _ member. entity;} internal set {_ member. entity = value; memberid = value. memberid ;}}}}
Implementing the auction Repositories
Now that the LINQ to SQL mappings are set up, it's dead easy to provide a full implementation of the repositories outlined earlier:
There are still some tools and techniques I will talk in the other chapter embedded...
§ Summary
In this chapter, you got up to speed withCore conceptsUnderpinning ASP. net mvc, andToolsAndTechniquesNeeded for successful web development with. NET and C #3 or later. In the next chapter, you'll use this knowledge to buildA real ASP. net mvc e-commerce application, Combining MVC Architecture, loosely coupled components,Unit Testing, AndA clean Domain ModelBuilt with an objectrelational mapping (ORM) Tool.
let's go to the next chapter now ~!