Cấp bậc tác giả:

TRAINING

[TUT .netTiers]Giới thiệu Database và SQL

Được viết bởi webmaster ngày 14/05/2013 lúc 11:09 PM
Bài trước Tôi đã giới thiệu căn bản về .netTiers, một trong những bộ Template sinh code tự động theo mô hình n-tiers từ database. Bài tiếp theo này Tôi sẽ tiếp tục giới thiệu về Database và SQL, đó sẽ là cách để bạn tiếp cận nó. Tuy nhiên, bạn cần xem qua hướng dẫn cách genecode trước khi đọc bài này.
  • 0
  • 10081

[TUT .netTiers]Giới thiệu Database và SQL

Bài trước Tôi đã giới thiệu căn bản về .netTiers, một trong những bộ Template sinh code tự động theo mô hình n-tiers từ database. Bài tiếp theo này Tôi sẽ tiếp tục giới thiệu về Database và SQL, đó sẽ là cách để bạn tiếp cận nó. Tuy nhiên, bạn cần xem qua hướng dẫn cách genecode trước khi đọc bài này

Mẫu Database và Sql:

Bằng cách nào .NetTiers tìm ra để tạo tự động? .netTiers sử dụng các siêu dữ liệu phong phú CodeSmith cung cấp được tìm thấy từ cơ sở dữ liệu để tạo ra một đối tượng hoàn chỉnh dựa trên mối quan hệ dữ liệu của bạn. SchemaExplorer cung cấp thông tin về Database, Table, View, Indexes, StoredProcedures,... Có một số khía cạnh quan trọng cần lưu ý khi tạo hoặc sử dụng cơ sở dữ liệu hiện có.

Bài tập:
Tên bảng là singular và Pascal Case(chữ cái đầu viết hoa, còn lại viết thường). VD: Order, Product, File
Các trường là Pascal Case(Viết hoa đầu từ). VD: FirstName, LastName, MiddleInitial
Mô tả được cung cấp cho các Bảng, Cột, và phím như một thuộc tính mở rộng.
Đối với MSSQL, đó là "MS_Description" quan trọng đối với các thuộc tính mở rộng.
Sử dụng tùy chọn ParseDbColDefaultVal có thể nhận được.NetTiers mặc định thuộc tính thực thể bằng cách sử dụng cơ sở dữ liệu mặc định. Ghi nhớ rằng hằng số chỉ đơn giản và một vài chức năng được hỗ trợ (getdate(), getutcdate()). Người dùng định nghĩa schema mặc định không được hỗ trợ
.netTiers không thể giả định quan hệ, mà bạn thực sự tạo ra các khóa ngoại liên quan đến khóa chính của bảng cha.

Relationships
Với bảng sau đây, chúng ta sẽ tạo quan hệ 1-1.

-- Create the Base Relationship, has a unique primary key amongst both tables.
CREATE TABLE [dbo].[Person](
    [PersonId] [int] NOT NULL,
    [Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
(
    [PersonId] ASC
) WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]


--Create the other side of the 1:1 relationship   
CREATE TABLE [dbo].[Contact](
    [ContactPersonId] [int] NOT NULL,
    [ContactNumber] [varchar](30) ,
CONSTRAINT [PK_Contact] PRIMARY KEY CLUSTERED 
(
    [ContactPersonId] ASC
) WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

-- Example of 1:1 relationship
-- The contact primary key is the is also a foreign key relationship to the PersonId.  
-- Therefore creating a 1:1 relationship.

ALTER TABLE [dbo].[Contact]  WITH CHECK ADD  CONSTRAINT [FK_Contact_Person]     
FOREIGN KEY([ContactPersonId])
REFERENCES [dbo].[Person] ([PersonId])
GO 

Thực thể bạn tạo ra sẽ trông thế này. Mỗi thực thể Person, bạn sẽ có thuộc tính tổng hợp đến thực thể Contact.

 /// <summary>
///    Holds a Contact object
///    which is related to this object through the relation Contact
/// </summary>
[BindableAttribute()]
public Contact Contact
{
    get { return entityData.Contact; }
    set { entityData.Contact = value; }    
}

Đối với mỗi thực thể Contact, khi bạn làm việc với các khóa ngoại, đó là khóa chính, bạn sẽ nhận được PersonId và PersonIdSource kiểu Parent.

private Person _contactPersonIdSource = null;

/// <summary>
/// Gets or sets the source <see cref="Person"/>.
/// </summary>
/// <value>The source Person for ContactPersonId.</value>
[Browsable(false), BindableAttribute()]
public virtual Person ContactPersonIdSource
{
    get { return this._contactPersonIdSource; }
    set { this._contactPersonIdSource = value; }
}

Using Collection Relationships.

Tùy chỉnh cho phiên bản ngắn gọn của một vài Northwind Database quen thuộc.

    -- ORDER
    -- A familiar pattern in database design, which is the Header/Details pattern in which 
    -- one table contains the the overall summary of all the 
    -- detail items contained within a particular detail Table.
    -- Think of a single order always *could* potentially have many order items.  
    -- Just like on your grocery receipt. 
    
    -- the Header Table
    CREATE TABLE [dbo].[Orders](
        [OrderID] [int] IDENTITY(1,1) NOT NULL,
        [CustomerID] int NOT NULL,
        [EmployeeID] [int] NULL,
     CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED 
    (
        [OrderID] ASC
    ) ON [PRIMARY]
    ) ON [PRIMARY]


    -- the Details Table
    CREATE TABLE [dbo].[Order Details](
        [OrderID] [int] NOT NULL,
        [ProductID] [int] NOT NULL,
     CONSTRAINT [PK_Order_Details] PRIMARY KEY CLUSTERED 
    (
        [OrderID] ASC,
        [ProductID] ASC
    ) ON [PRIMARY]
    ) ON [PRIMARY]

    -- the Customer Table
    CREATE TABLE [dbo].[Customer](
        [CustomerID] [int] NOT NULL,
        [ContactName] [nvarchar](30) NULL,
     CONSTRAINT [PK_Customers] PRIMARY KEY CLUSTERED 
    (
        [CustomerID] ASC
    ) ON [PRIMARY]
    ) ON [PRIMARY]



    --Example of Many To One relationship:
    -- This creates a simple relationship between the Orders Table and the Customer, so that in your 
    -- for every OrderEntity entity, you will have a CustomerId foreign key integer, and a 
    -- CustomerIdSource entity of type Customer nested composite entity in your Order class.    

ALTER TABLE [dbo].[Order]  WITH NOCHECK ADD  CONSTRAINT [FK_Order_Customer] 
    FOREIGN KEY([CustomerID])
    REFERENCES [dbo].[Customer] ([CustomerID])
    GO 

        --Example of One to Many Relationship:
    -- This creates a one to many relationship between the Order and the Order Detail tables.  
    -- Meaning, in your generated code, 
    -- for every Order entity, you will have an OrderDetailCollection of type TList<OrderDetail>.  
    -- This means you can have an entire
    -- list of OrderDetail entities within your Order entity.
    
ALTER TABLE [dbo].[Order Details]  WITH NOCHECK ADD  CONSTRAINT [FK_Order_Details_Orders]             FOREIGN KEY([OrderID])
    REFERENCES [dbo].[Orders] ([OrderID])
    GO

Quan hệ n-n

Cuối cùng của quan hệ nội tại là nhiều-nhiều. m: mối quan hệ m bao gồm 3 bảng là bảng bên trái, bảng giao, bảng bên phải và bản chất là linh hoạt 1: m nhưng quan hệ với hai bảng bằng cách sử dụng giao để tạo thuận lợi cho quan hệ. Ví dụ bảng Orders, Order Details, và Products. Trường hợp để có thể có nhiều chi tiết đơn hàng mà tất cả đều có sản phẩm, trong khi cùng một lúc sản phẩm có thể được ở Chi tiết Đặt hàng được liên kết với nhiều đơn đặt hàng. Bảng giao nhau này nắm giữ cả hai tham chiếu đến các bảng bên trái và bên phải. Chúng ta có thể suy ra từ thực thể Order rằng các thực thể tự sẽ có bộ sưu tập các kiểu TList và tương tự sẽ thấy bộ sưu tập Order cho tất cả Product do bảng giao của Order Datails

    ALTER TABLE [dbo].[Order Details]  WITH NOCHECK ADD  CONSTRAINT [FK_Order_Details_Orders]         FOREIGN KEY([OrderID])
    REFERENCES [dbo].[Orders] ([OrderID])
    GO

    Alter TABLE [dbo].[Order Details]  WITH NOCHECK ADD  CONSTRAINT [FK_Order_Details_Products]     FOREIGN KEY([ProductID])
    REFERENCES [dbo].[Products] ([ProductID])
    GO

    // Order Entity:
     
    /// <summary>
    ///    Holds a collection of ProductsFromOrderDetails objects
    ///    which are related to this object with junction table OrderDetails
    /// </summary>    
    [BindableAttribute()]
    public TList<Products> ProductsCollection_From_OrderDetails
    {
        get { return entityData.ProductsCollection_From_OrderDetails; }
        set { entityData.ProductsCollection_From_OrderDetails = value; }    
    }

    //Product Entity:

    /// <summary>
    /// Holds a collection of OrdersFromOrderDetails objects
    /// which are related to this object through junction table OrderDetails
    /// </summary>    
    [BindableAttribute()]
    public TList<Orders> OrdersCollection_From_OrderDetails
    {
       get { return entityData.OrdersCollection_From_OrderDetails; }
       set { entityData.OrdersCollection_From_OrderDetails = value; }    
    }

Indexes

Indexes(Chỉ số) không chỉ là tính năng mạnh mẽ để giúp cải thiện thực hiện truy vấn trở nên hoàn hảo hơn, nó cũng được sử dụng để tạo ra tiện dụng truy cập dữ liệu phương thức API dựa trên chỉ số. Tính năng quan trọng của chỉ số là nó có thể chứa cột 1-n và có khả năng được thiết lập như chỉ số UNIQUE.

Ví dụ, trong bảng Person chúng ta tạo ra ở trên, nếu chúng ta thêm chỉ số vào cột Name, và cột là Unique. Thì trong dữ liệu của tôi truy cập API tôi sẽ có được phương thức gọi Person là GetByName(string name). Nếu tôi đã không cho chỉ số là unique, thì phương thức này sẽ trả về bộ sưu tập(collection) kiểu TList.

SQL
 CREATE UNIQUE NONCLUSTERED INDEX [IX_Person] ON [dbo].[Person] 
    (
        [Name] ASC
    )WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [PRIMARY]

OUTPUT:
        /// <summary>
        ///    Gets rows from the datasource based on IX_Person index.
        /// </summary>
        /// <param name="name"></param>
        /// <returns>Returns an instance of the <see cref="Person"/></returns>
        public Person GetByName(System.String name)
        {
            int count = -1;
            //Calls Provider specific Implementation 

            return GetByName(null,name, 0, int.MaxValue, out count);
        }

Tùy chỉnh Stored Procedures

Nhiều khi bạn muốn mở rộng truy cập dữ liệu API, nhưng bạn vẫn muốn tận dụng nhiều cách tiếp cận để tạo ra tầng data .netTiers khả năng viết các thủ tục riêng và có thể làm những việc đó.

Ví dụ, nếu bạn muốn tạo ra tùy chỉnh thủ tục lưu trữ để xử lý nhận được tất cả các sản phẩm dưới hàng tồn kho nhất định. Khi bạn bắt đầu quá trình tạo, CodeSmith SchemaExplorer sẽ cố gắng để khám phá tất cả các thông tin dữ liệu phong phú được cung cấp để xác định các thủ tục này trả về tập kết quả, các thông số cần (đầu vào và đầu ra).

 -- Get the products that have less units in stock than the @UnitsInStock parameter.
 CREATE PROCEDURE dbo._Product_GetWithStockBelow
    @UnitsInStock smallint
 AS

   SELECT
        [ProductID],
        [ProductName],
        [SupplierID],
        [CategoryID],
        [QuantityPerUnit],
        [UnitPrice],
        [UnitsInStock],
        [UnitsOnOrder],
        [ReorderLevel],
        [Discontinued]
   FROM
   [dbo].[Product]
   WHERE
        [UnitsInStock] < @UnitsInStock
 GO

Output:
        public TList<Product> GetWithStockBelow(System.Int16 unitsInStock)
        {

            int count = -1;
            //Calls Provider specific Implementation 

            return GetWithStockBelow(
                null, unitsInStock, 0, int.MaxValue, out count);

        }

Chú ý: Có một số tình huống mà thủ tục sẽ không trả lại kết quả như mong đợi. Tùy chỉnh Stored procedures không làm việc khi sử dụng bảng tạm trong tùy chỉnh Stored procedures. Điều này là do khi SchemaExplorer CodeSmith khám phá thông tin này, nó không có priveldges cần thiết để tạo ra bảng tạm. Một cách giải quyết là sử dụng biến bảng trong thủ tục lưu trữ thay vì bảng tạm. 

Cảnh báo: Bảng biến được tổ chức trong bộ nhớ trên máy chủ, do đó, không tải quá nhiều hàng trong bảng biến hoặc thực hiện các máy chủ sẽ bị ảnh hưởng.

Lưu ý: Để netTiers trả về thực thể các bản đồ đến bảng bạn đã tạo tùy chỉnh  Stored Procedure, tất cả các cột được trả lại phải phù hợp với kiểu và theo thứ tự chính xác. Do đó nó được khuyến khích SELECT * từ các bảng mã nguồn có thể thay vì xác định mỗi cột trong việc chọn.

Nếu bạn nhận thấy các mã được tạo ra cho tùy chỉnh SP trả lại "void" thay vì bạn mong đợi kiểm tra xem bạn tùy chỉnh SP hợp lệ chưa

Bảng Enums

.netTiers tạo enums dựa trên bảng dữ liệu cho bảng mà bạn chỉ định. Điều này rất hữu ích cho các dữ liệu tương đối tĩnh hoặc kiểu bảng.

Quy tắc: Các bảng bạn muốn tạo ra như enums phải đáp ứng các quy tắc sau đây. 
1. Cột đầu tiên phải là khóa chính (thường này sẽ là cột Identity int)
2. Cột thứ hai phải có một số hạn chế cột độc đáo, cột thứ ba tùy chọn sẽ là mô tả của việc tạo enum. 
3. Bạn cũng phải chọn bảng này trong SourceTable để tạo ra các enum.

Ví dụ:

CREATE TABLE [dbo].[BankAccountType](
    [BankAccountTypeId] [int] IDENTITY(1,1) NOT NULL,
    [BankAccountTypeName] [varchar](50) NOT NULL,
    [BankAccountTypeDescription] [varchar](250)NULL,
 CONSTRAINT [BankAccountType_PK] PRIMARY KEY CLUSTERED 
(
    [BankAccountTypeId] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY],
 CONSTRAINT [BankAccountType_UC1] UNIQUE NONCLUSTERED 
(
    [BankAccountTypeName] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

-- Add Table Description
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'All allowable Checking Account types for my ABC System' ,@level0type=N'SCHEMA', @level0name=N'dbo', @level1type=N'TABLE', @level1name=N'BankAccountType'


--Some Enum Items:
INSERT INTO [dbo].[BankAccountType] VALUES ('Checking', 'A Valid Checking Account')
INSERT INTO [dbo].[BankAccountType] VALUES ('Savings', 'A Valid Savings Account')

Tạo ra Enumeration

    /// <summary>
    /// All allowable Checking Account types for my ABC System
    /// </summary>
    /// <remark>Enum that contains the items in BankAccountType</remark>
    [Serializable]
    public enum BankAccountTypeList
    {

        /// <summary> 
        /// A Valid Checking Account
        /// </summary>
        [EnumTextValue("A Valid Checking Account")]
        Checking = 1, 


        /// <summary> 
        /// A Valid Savings Account
        /// </summary>
        [EnumTextValue("A Valid Savings Account")]
        Savings = 2
    }

Bài tiếp theo Tôi sẽ giới thiệu về Layer Entity - một kiểu thực thể quan hệ quan trọng trong Teamplate .netTiers

Nguồn bài viết: DOTNET.VN

BÌNH LUẬN BÀI VIẾT

Bài viết mới nhất

LIKE BOX

Bài viết được xem nhiều nhất

HỌC HTML