• ASP.NET MVC2 第三章Ⅰ


    Before next chapter’s deep dive into a real ASP.NET MVC e-commerce development experience, it’s important to make sure you’re familiar with the architecture, design patterns, tools, and techniques that 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 automated 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:

    • Models
    • Views
    • Controller

    §3.1.1  The Smart UI (Anti-Pattern)

    ignore

    §3.1.2  Separating Out the Domain Model

    Model-View Architecture

    architecture as shown:

    1

    §3.1.3 Three-Tier Architecture

    architecture as shown:

    2

    §3.1.4  MVC Architecture

    architecture as shown:

    3

    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 Rails is the most famous MVC poster child, but Apache Struts, Spring MVC, and many 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 called a domain model.This component is extremly important to your software. Everything else, including controllers and views, is just a technical detail designed to support or permit interaction 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:

    4

    This diagram indicates 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

    5

    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 your domain objects into and out of some kind of persistent 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 define repositories.When you’re working with aggregates, it’s normal to define a 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 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 item) { /* Implement me */ }
            public Item FetchByID(int itemID) {return new Item(); /* Implement me */ }
            public IList<Item> ListItems(int pageSize, int pageIndex) { return new Item[] { new Item() }; /* Implement me */ }
            public void SubmitChanges() { /* Implement me */ }
        }

    Notice that repositories are concerned only with loading and saving data, and contain as little domain logic as is possible.In this example, you’ll see how to use an ORM 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 such as NHibernate, but sometimes easier to use, considering its full support for LINQ and its inclusion by default in all editions of Visual Studio 2008 and 2010.

    DataContext is your entry point to the whole LINQ 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, it keeps track of any changes you 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 various different 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 classes with special attributes or by writing an XML 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 with the core concepts underpinning ASP.NET MVC, and the tools and techniques needed for successful web development with .NET and C# 3 or later. In the next chapter, you’ll use this knowledge to build a real ASP.NET MVC e-commerce application, combining MVC architecture, loosely coupled components, unit testing, and a clean domain model built with an objectrelational mapping (ORM) tool.

    LET'S GO TO THE NEXT CHAPTER NOW~!

  • 相关阅读:
    从程序员到项目经理(13):如何管理自己的时间(下)
    从程序员到项目经理(11):每个人都是管理者
    从程序员到项目经理(15):项目管理三大目标
    程序员:伤不起的三十岁
    从程序员到项目经理(9):程序员加油站 再牛也要合群
    从程序员到项目经理(7):程序员加油站 完美主义也是一种错
    从程序员到项目经理(4):外行可以领导内行吗
    ArcGIS API For Android离线地图的实现
    ArcGIS for Android地图控件的5大常见操作
    从程序员到项目经理(16):原来一切问题都是可以解决的
  • 原文地址:https://www.cnblogs.com/TivonStone/p/1851733.html
Copyright © 2020-2023  润新知