軟體開發(軟件開發)

網智數位主要提供套裝及客製化的軟體系統解決方案,專為客戶量身訂做客製化的軟體,達成客製化、智慧化及網路化的管理功能。

室內設計、裝潢、窗簾報價估算軟體

網智數位主要提供套裝及客製化的軟體系統解決方案,針對室內設計師、木工、裝潢業產業,量身訂做客製化的軟體,達成客製化、智慧化及網路化的商用軟體。

商用軟體-客製化設計

網智數位主要提供套裝及客製化的軟體系統解決方案,專為客戶量身訂做客製化的軟體,達成客製化、智慧化及網路化的管理功能。

IOT 物聯網-系統開發

根據客戶實際狀況,結合雲端與載具進行客製化物聯網IOT導入與軟體開發

雲端VPS虛擬主機租用

我們的雲端VPS虛擬主機是採用雲端(虛擬化)技術所開發之全新雲端伺服器服務,可以選擇多種作業系統(Windows、Linux等),客戶可載入自訂的應用環境,執行自己所要提供的網路服務,我們的雲端服務可為您的網站提供最完美的解決方案。

ERP軟體客製化導入

ERP軟體客製化導入,室內設計、營造業、裝潢、木作工程、系統櫃工程、會計系統,全面提升公司管理營運效率。

搜尋引擎最佳化SEO

搜尋引擎最佳化(SEO)不僅能提高網站在搜尋結果的排名,更能帶來大量對我們產品或服務真正有需求的訪客。SEO 最棒的特質之一就是不像廣告一樣亂槍打鳥而導致用戶的反感,反而更能提升點閱率跟成交率喔。

服務宗旨

網智數位主要提供套裝及客製化的軟體系統解決方案,專為客戶量身訂做客製化的軟體,達成客製化、智慧化及網路化的管理功能。

我們的成立宗旨就是要以最猛的IT技術讓這個世界更Smart,在我們貫徹我們裡想的同時,我們希望可以把我們所開發的系統帶給台灣的中小企業,除了要推薦好的東西之外,我們也希望做點改變,所以我們的第一目標就是要使用最好用的系統再加上您寶貴的創意,不僅僅可以節省你大量的荷包,還可以有一個像樣的網站。我們可以幫你做的有

企業管理
  • 策略管理
  • 目標管理
  • 行銷管理
  • 財會管理
  • ERP導入
  • 企業流程自訂
資訊管理
  • 網站架設
  • 虛擬化/雲端架設
  • 主機代管
  • 私有雲建制與導入
軟體開發
  • UML設計
  • 版本控管
  • 企業軟體開發
  • APP開發
  • 網頁設計
資訊安全
  • 網頁弱點掃描
  • 主機弱點掃描
  • 木馬檢測
  • 資安鑑識
  • 設計網路架構
  • 資安監控
行銷
  • 關鍵字SEO
  • 社群網路行銷
  • 部落格行銷
  • FaceBook 粉絲團
其他
  • 協助企業申請Google Email
好玩工具開發

講出你的創意吧!沒有甚麼是資訊辦不到的

顯示具有 LINQ 標籤的文章。 顯示所有文章
顯示具有 LINQ 標籤的文章。 顯示所有文章

2015年11月28日 星期六

Entity Framework 實戰 - 多對多自我關聯 Many to Many , Self Referencing 模型實作 (二)

此篇文是 Entity Framework 實戰 - 多對多自我關聯 Many to Many , Self Referencing 模型實作 (一)的續篇 , 當我們把基本模型 Product Class 建立好後,我們開始實作一個繼承 DbContext 的子類別,在這邊你可以把 DbContext 當做是資料庫的層次意義角度來看待
新增一個Class 名為 ProductContext.cs
image
然後按【新增】按鈕,並在 ProductContext 宣示繼承 DbContext 類別,如以下程式碼
  1: using System;
  2: using System.Collections.Generic;
  3: using System.Data.Entity;
  4: using System.Linq;
  5: using System.Text;
  6: using System.Threading.Tasks;
  7: 
  8: namespace EF6_ManyToManyAndSelf
  9: {
 10:     public class ProductContext : DbContext
 11:     {
 12: 
 13:     }
 14: }

接著加入 DbSet<Product> 的宣告,用於表示 存放著 Product Table(Class)的集合清單
public DbSet<Product> Products;
然後為了完成透過 Product 本身的 Class 來完成 多對多自身關聯,需要 override OnModelCreating Method , 程式碼如下

   1:   protected override void OnModelCreating(DbModelBuilder modelBuilder)
   2:          {
   3:              base.OnModelCreating(modelBuilder);
   4:   
   5:              modelBuilder.Entity<Product>()
   6:                          .HasMany(p => p.RelatedProducts)
   7:                          .WithMany(p => p.AboveProducts)
   8:                          .Map(m =>
   9:                                    {
  10:                                        m.MapLeftKey("ProductID");
  11:                                        m.MapRightKey("RelatedProductID");
  12:                                        m.ToTable("RelatedProduct");
  13:                                    }
  14:                          );
  15:          }

到這邊基本上已經完成 EntityFramework 的宣告….

然後讓我們在前端界面使用我們實作好的 ProductContext ,來看看如何使用….程式碼如下


   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Threading.Tasks;
   6:   
   7:  namespace EF6_ManyToManyAndSelf
   8:  {
   9:      class Program
  10:      {
  11:          static void Main(string[] args)
  12:          {
  13:              using (var context = new ProductContext())
  14:              {
  15:                  var product1 = new Product { ProductName = "美容業零售管理系統", Price = 59888M };
  16:                  var product2 = new Product { ProductName = "窗簾業ERP系統", Price = 3500000M };
  17:                  var product3 = new Product { ProductName = "玩具製造業ERP系統", Price = 6700000M };
  18:                  product2.RelatedProducts.Add(product3);
  19:                  product1.RelatedProducts.Add(product2);
  20:                  context.Products.Add(product1);
  21:                  context.SaveChanges();
  22:              }
  23:              using (var context = new ProductContext())
  24:              {
  25:                  var product2 = context.Products.First(p => p.ProductName == "窗簾業ERP系統");
  26:                  Console.WriteLine("Product: {0} ... {1}", product2.ProductName, product2.Price.ToString("C"));
  27:                  Console.WriteLine("Related Products");
  28:                  foreach (var prod in product2.RelatedProducts)
  29:                  {
  30:                      Console.WriteLine("\t{0} ... {1}", prod.ProductName, prod.Price.ToString("C"));
  31:                  }
  32:                  foreach (var prod in product2.AboveProducts)
  33:                  {
  34:                      Console.WriteLine("\t{0} ... {1}", prod.ProductName, prod.Price.ToString("C"));
  35:                  }
  36:              }
  37:   
  38:              Console.ReadKey();
  39:          }
  40:      }
  41:  }


 
 



執行結果為


image





網智數位-軟體開發(軟件開發)

Entity Framework 實戰 - 多對多自我關聯 Many to Many , Self Referencing 模型實作 (一)

在我們軟體開發過程中,我們會遇到一種特殊模型實體關係,例如一個線上商品系統,會有產品資料表(Product Table),以及記錄產品的【相關產品】和該產品本身可以被關聯的上層【相關產品】,感覺很繞口,下圖我截取一個 ER-D 示例圖:
image
上圖ERD 關聯存在所謂的多對多關係 (Many to Many)而且又是自我關聯(自身關聯,Self Referencing),本身的主要邏輯是 RelatedProduct 這個Table,擔任一個用來記錄多對多關聯記錄的中繼Table,RelatedProduct Table包含了2個欄位(ProductID、RelatedProductID),2個欄位都是參考(Referencing)到 Product Table的 ProductID 主鍵值 ( Primary Key ),透過這樣的技巧可以表達一個產品可以關聯多個相關產品,反之也可以表達一個產品可以被多少產品有所關聯….
但現在我要教大家實作一個只需要在 Entity Framework 建立一個 Product Model (POCO),然後透過一些程式寫法技巧,來達成 這種商業資料模型  - 》 多對多自我關聯 Many to Many , Self Referencing 。
首先讓我們用 Visual Studio 開發工具來先新增一個程式專案,在此我程式專案命名為 EF6_ManyToManyAndSelf,然後按確定。
image
接下來,我們需要透過 NuGet來安裝 EntityFramework ,
image
image
在上圖執行安裝按鈕後,後續 NuGet 就會開始安裝 EntityFramewok , 目前 Allen 裝的版本為 6.1.3 穩定版,安裝過程可能會等候一點點時間,裝完後,你會發現專案的參考對了2個參考項目
image
確定沒問題後,接下來我們來新增一個 Product Class ,用來代表 Product table 的對應,完整程式碼如下:
image
   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.ComponentModel.DataAnnotations;
   4:  using System.ComponentModel.DataAnnotations.Schema;
   5:  using System.Linq;
   6:  using System.Text;
   7:  using System.Threading.Tasks;
   8:   
   9:  namespace EF6_ManyToManyAndSelf
  10:  {
  11:      [Table("Product", Schema = "dbo")]
  12:      public class Product
  13:      {
  14:          public Product()
  15:          {
  16:              RelatedProducts = new HashSet<Product>();
  17:              AboveProducts = new HashSet<Product>();
  18:          }
  19:   
  20:          [Key]
  21:          [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  22:          public int ProductID { get; set; }
  23:   
  24:          public string ProductName { get; set; }
  25:   
  26:          public decimal Price { get; set; }
  27:   
  28:          /// <summary>
  29:          /// 記錄此產品的多個相關的產品
  30:          /// </summary>
  31:          public virtual ICollection<Product> RelatedProducts { get; set; }
  32:   
  33:          /// <summary>
  34:          /// 記錄此產品被那些上層產品標示為相關的產品
  35:          /// </summary>
  36:          public virtual ICollection<Product> AboveProducts { get; set; }
  37:   
  38:      }
  39:  }
 

    實作到這邊已經把基本的 EntityFramework 安裝進來,也把產品模型寫成一個POCO Class ,後續是更進階的 程式技巧已經背後運作解釋,請繼續參閱我撰寫  Entity Framework 實戰 - 多對多自我關聯 Many to Many , Self Referencing 模型實作 (二) 的介紹。



網智數位-軟體開發 (軟件開發)

2014年11月12日 星期三

[Entity Framework] 效能深入探討(二)

     在上一篇我花了一些時間談到,當我們載入資料庫模型是屬於 1 對多 (One-To-Many)時,預設值 Entity Framework 6 是利用一個稱為 Lazy Loading 機制,也就是當需要一個資料的其他相關(關聯)資料時,EF 才會產生SQL語法去跟後端資料庫要求相關資料,而資料應用程式效能的殺手之一,就是太繁複去跟後端資料庫來回存取,為了克服 EF 預設行為的效能問題,我想來介紹一個 EF 另外一個機制術語,稱為 Eager Loading ....


 

     使用 Eager Loading 機制,主要可以在一開始讀取資料時,例如讀取 Customer Table 時,如果我們知道後續一定會讀取相關聯的資料表(類別),如案例的 CustomerCate Table、CustomerEvent Table,那麼我們就可以在第一次讀取 Customer Table 時就一次讀取所有相關的資料表,這樣後續應用程式需要相關資料時,只要在記憶體立即讀取,而不是需要用到時,才延遲跟資料庫索取相關資料,解釋那麼多,到底程式語法該如何實作呢?我們會用到一個方法(Method)為 Include ....

    PS.這次實作我完全根據 上一篇[Entity Framework] 效能深入探討(一) 繼續介紹,前端我暫時利用 Windows Form 來簡單的 Demo
,然後我會把焦點放在 Include Loading(1) 與  Include Loading(2) 的 程式語法
 

在  Include Loading(1) Button Click事件,我撰寫了一些程式碼:

  1. this.richTextBox1.Clear();
  2. this.richTextBox1.AppendText("使用 Eager Loading 機制 Include Method ! \r\n");
  3. this.richTextBox1.AppendText("------------------------------------------------------------------------- \r\n");

  4. using (CRMEF ef = new CRMEF())
  5. {
  6.      var customers = ef.Customer.Include("CustomerCate").Include("CustomerEvent");

  7.      foreach (var cust in customers)
  8.      {
  9.           this.richTextBox1.AppendText("客戶編號 : " + cust.No + " 客戶姓名 :" + cust.ENmae + "\t  類型 :" + cust.CustomerCate.Name + "\r\n");
  10.           this.richTextBox1.AppendText("--------------------------------事件記錄------------------------------------ \r\n");

  11.           foreach (var evt in cust.CustomerEvent)
  12.           {
  13.                this.richTextBox1.AppendText(evt.Desc + "\r\n");
  14.           }

  15.           this.richTextBox1.AppendText("\r\r\n");
  16.      }
  17. }

     注意上述程式碼的第 7 行我使用了2次 Include 方法,並在該方法傳遞是關聯類型的字串,透過這樣的方式,但程式第一次需要讀取 Customer 資料表時,
Entity Framewok(EF)就會自動產生的 SQL語法是把 Customer、CustomerCate、CustomerEvent 3個 Table,一次完全跟後端資料庫的索取,並記錄到記憶體(DataContext Cache),所以整個 SQL 傳輸只有 1 次,而不是上一篇介紹的 7 次哦(效能差很大,這也是一般書上很少寫的)。

底下我列出我追蹤的 SQL 語法如下
  1. SELECT
  2.     [Project1] .[C1] AS [C1],
  3.     [Project1] .[No] AS [No],
  4.     [Project1] .[CName] AS [CName],
  5.     [Project1] .[ENmae] AS [ENmae],
  6.     [Project1] .[CateCode] AS [CateCode],
  7.     [Project1] .[Code] AS [Code],
  8.     [Project1] .[Name] AS [Name],
  9.     [Project1] .[C2] AS [C2],
  10.     [Project1] .[EventID] AS [EventID],
  11.     [Project1] .[CustNo] AS [CustNo],
  12.     [Project1] .[Desc] AS [Desc],
  13.     [Project1] .[CreateDate] AS [CreateDate]
  14.      FROM ( SELECT
  15.         [Extent1] .[No] AS [No],
  16.         [Extent1] .[CName] AS [CName],
  17.         [Extent1] .[ENmae] AS [ENmae],
  18.         [Extent1] .[CateCode] AS [CateCode],
  19.         [Extent2] .[Code] AS [Code],
  20.         [Extent2] .[Name] AS [Name],
  21.         1 AS [C1],
  22.         [Extent3] .[EventID] AS [EventID],
  23.         [Extent3] .[CustNo] AS [CustNo],
  24.         [Extent3] .[Desc] AS [Desc],
  25.         [Extent3] .[CreateDate] AS [CreateDate],
  26.          CASE WHEN ([Extent3]. [EventID] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C2]
  27.          FROM   [dbo]. [Customer] AS [Extent1]
  28.          LEFT OUTER JOIN [dbo] .[CustomerCate] AS [Extent2] ON [Extent1] .[CateCode] = [Extent2].[Code]
  29.          LEFT OUTER JOIN [dbo] .[CustomerEvent] AS [Extent3] ON [Extent1] .[No] = [Extent3].[CustNo]
  30.      )  AS [Project1]
  31.      ORDER BY [Project1].[No] ASC, [Project1] .[Code] ASC , [Project1]. [C2] ASC


看吧看吧,是不是 EF很聰明的產生一個完全都包含的表格(Table)。


接下來,我們來看第二種 Include 語法的寫法,2種執行結果都相同。

  1. this.richTextBox1.Clear();
  2. this.richTextBox1.AppendText("使用 Eager Loading 機制 Include Method 2 ! \r\n");
  3. this.richTextBox1.AppendText("------------------------------------------------------------------------- \r\n");

  4. using (CRMEF ef = new CRMEF())
  5. {
  6.      var customers = ef.Customer.Include(t => t.CustomerCate).Include(t => t.CustomerEvent);

  7.      foreach (var cust in customers)
  8.      {
  9.           this.richTextBox1.AppendText("客戶編號 : " + cust.No + " 客戶姓名 :" + cust.ENmae + "\t  類型 :" + cust.CustomerCate.Name + "\r\n");
  10.           this.richTextBox1.AppendText("--------------------------------事件記錄------------------------------------ \r\n");

  11.           foreach (var evt in cust.CustomerEvent)
  12.           {
  13.                this.richTextBox1.AppendText(evt.Desc + "\r\n");
  14.           }

  15.           this.richTextBox1.AppendText("\r\r\n");
  16.      }
  17. }

以上介紹完 Eager Loading Inclue 的技巧,希望各位操控 EntityFramework 6 可以更加熟析在最適當的狀況下,來調整預設存取行為機制。



2014年11月2日 星期日

【EntityFramework 實戰】 一對多關聯

     這篇教學文件,我想一步一步的教讀者如何利用 EntityFramework 來寫一對多 (One-To-Many) 關聯 Table的程式碼技巧,並且分別利用 Entity SQL
LINQ To SQL  的方式來讀取資料庫。

在實例個案,我們常常會遇到如下的資料表一對多關聯

(SQL 語法)
  1. CREATE TABLE Employee
  2. (
  3.   [No] NVARCHAR( 12) NOT NULL PRIMARY KEY,
  4.   HireDate Datetime not null default(getdate ()),
  5.   Name NVARCHAR( 12) NOT NULL
  6. )

  7. CREATE TABLE EmployeeSalary
  8. (
  9.  EmpNo NVARCHAR(12) NOT NULL,
  10.  PayYear INT NOT NULL,
  11.  PayMonth INT NOT NULL,
  12.  bonus DECIMAL(18,2) NOT NULL,
  13.  constraint PK_EmployeeSalary primary key (EmpNo,PayYear,PayMonth),
  14.  constraint FK_EmployeeSalary foreign key (EmpNo)
  15.       references Employee ([No])
  16. )


          在上述案例,我們可以知道一個員工(Employee)在每年的每個月有可能因為績效達到某些企業設定的條件,因此可以得到應領取的獎金(EmployeeSalary) , 但也有可能某員工為新進員工,所以雖然在 Employee 資料表存在記錄,但 EmplyeeSalary 卻不存在任何記錄,如果此時企業的系統應用要求,列出所有員工(不論是否已有任何獎金),如有獎金也顯示出在前端界面,我們該如何利用 EntityFramework 去實戰這個很普遍到不行的案例呢? 下面我就示範出比較適當的程式技巧。

首先在此我一樣是利用 Code-First Style 來操控 EntityFramework , 並前端界面我利用Windows Form來示範,前端界面圖示如下

在寫入資料 Button ,我先示範利用 EntityFramewok,來寫入所需的測試資料

     1:    private void btnInsert_Click(object sender, EventArgs e)  
     2:          {  
     3:              using (DBEntities entities = new DBEntities())  
     4:              {  
     5:                  Employee emp1 = new Employee()  
     6:                                  {  
     7:                                      No = "001", //員工編號  
     8:                                      HireDate = DateTime.Parse("2014/05/01"), //僱用日期  
     9:                                      Name = "湯姆克魯斯", //員工姓名                                       
    10:                                  };  
    11:                  EmployeeSalary salary1 = new EmployeeSalary()  
    12:                                           {  
    13:                                               bonus = 1000, //獎金  
    14:                                               PayYear = 2014, //年  
    15:                                               PayMonth = 9, //月                                                
    16:                                           };  
    17:                  emp1.EmployeeSalary.Add(salary1);  
    18:     
    19:                  Employee emp2 = new Employee()  
    20:                  {  
    21:                      No = "002", //員工編號  
    22:                      HireDate = DateTime.Parse("2014/06/01"), //僱用日期  
    23:                      Name = "李奧納多", //員工姓名                                       
    24:                  };  
    25:                  EmployeeSalary salary2_1 = new EmployeeSalary()  
    26:                  {  
    27:                      bonus = 1000, //獎金  
    28:                      PayYear = 2014, //年  
    29:                      PayMonth = 9, //月                                                
    30:                  };  
    31:                  emp2.EmployeeSalary.Add(salary2_1);  
    32:                  EmployeeSalary salary2_2 = new EmployeeSalary()  
    33:                  {  
    34:                      bonus = 6000, //獎金  
    35:                      PayYear = 2014, //年  
    36:                      PayMonth = 10, //月                                                
    37:                  };  
    38:                  emp2.EmployeeSalary.Add(salary2_2);  
    39:     
    40:     
    41:                  Employee emp3 = new Employee()  
    42:                  {  
    43:                      No = "003", //員工編號  
    44:                      HireDate = DateTime.Parse("2014/10/01"), //僱用日期  
    45:                      Name = "基諾李維", //員工姓名                                       
    46:                  };  
    47:     
    48:                  entities.Employee.Add(emp1);  
    49:                  entities.Employee.Add(emp2);  
    50:                  entities.Employee.Add(emp3);  
    51:     
    52:                  entities.SaveChanges();  
    53:              }  
    54:          }  

執行寫入資料按鈕後,後端資料庫結果為如下
 

測試資料有了以後,開始我們可以分別利用 Entity SQL 與 LINQ To Entities 兩種技巧來讀取

在 顯示資料(Entity SQL) 按鈕 ,程式如下
  
     1:   private void button1_Click(object sender, EventArgs e)  
     2:          {  
     3:              this.richTextBox1.Clear();  
     4:     
     5:              using(DBEntities entites = new DBEntities())  
     6:              {  
     7:                  var eSQL = @"SELECT A.No,A.Name,A.HireDate,B.PayYear,B.PayMonth,B.bonus  
     8:                                FROM Employee AS A OUTER APPLY A.EmployeeSalary AS B   
     9:                                ORDER BY A.No ";  
    10:                  var allEmpSalaryRecords = ((IObjectContextAdapter)entites).ObjectContext.CreateQuery<DbDataRecord>(eSQL).ToList();  
    11:     
    12:                  this.richTextBox1.AppendText("所有員工與獎金明細表:\r\n");  
    13:                  this.richTextBox1.AppendText("-------------------------------------------------------------------\r\n");  
    14:     
    15:                  //開始讀取  
    16:                  foreach(var empRecord in allEmpSalaryRecords)  
    17:                  {  
    18:                      if(empRecord["bonus"] != DBNull.Value)  
    19:                      {  
    20:                          this.richTextBox1.AppendText( "員工姓名 : " + empRecord["Name"].ToString() + " \r\n");  
    21:                          this.richTextBox1.AppendText("(年/月)  " + empRecord["PayYear"].ToString() + "/" + empRecord["PayMonth"].ToString()   
                                                                           + " 獎金為 " + empRecord["bonus"].ToString() + " \r\n");  
    22:     
    23:                      }  
    24:                      else  
    25:                      {  
    26:                          this.richTextBox1.AppendText("員工姓名 : " + empRecord["Name"].ToString() + " \r\n");  
    27:                          this.richTextBox1.AppendText(" 未有獎金 \r\n");  
    28:                      }  
    29:                  }  
    30:     
    31:              }  
    32:          }  

執行結果如下


在 顯示資料(LINQ) 按鈕 ,程式如下
  1. private void button2_Click(object sender, EventArgs e)
  2. {
  3.      this.richTextBox1.Clear();

  4.      using (DBEntities entities = new DBEntities())
  5.      {
  6.           var allEmpSalaryRecords = (from emp in entities.Employee
  7.                                            from empSalary in emp.EmployeeSalary.DefaultIfEmpty()
  8.                                            orderby emp.No
  9.                                            select new
  10.                                            {
  11.                                                 emp.Name,
  12.                                                 PayYear = (int?)empSalary.PayYear,
  13.                                                 PayMonth = (int?)empSalary.PayMonth,
  14.                                                 Bonus = (decimal?)empSalary.bonus
  15.                                            }).ToList();

  16.           //開始讀取
  17.           foreach (var empRecord in allEmpSalaryRecords)
  18.           {
  19.                if (empRecord.Bonus.HasValue)
  20.                {
  21.                     this.richTextBox1.AppendText("員工姓名 : " + empRecord.Name + " \r\n");
  22.                     this.richTextBox1.AppendText("(年/月)  " + empRecord.PayYear.ToString() + "/" + empRecord.PayMonth.ToString() 
  23.                                                                          + " 獎金為 " + empRecord.Bonus.ToString() + " \r\n");

  24.                }
  25.                else
  26.                {
  27.                     this.richTextBox1.AppendText("員工姓名 : " + empRecord.Name + " \r\n");
  28.                     this.richTextBox1.AppendText(" 未有獎金 \r\n");
  29.                }
  30.           }
  31.      }
  32. }
執行結果


透過以上2種讀取技巧,我追蹤EntityFramework 6都是自動產生以下 SQL 語法
  1. SELECT 
  2.     [Project1].[C1] AS [C1], 
  3.     [Project1].[No] AS [No], 
  4.     [Project1].[Name] AS [Name], 
  5.     [Project1].[HireDate] AS [HireDate], 
  6.     [Project1].[PayYear] AS [PayYear], 
  7.     [Project1].[PayMonth] AS [PayMonth], 
  8.     [Project1].[bonus] AS [bonus]
  9.     FROM ( SELECT 
  10.         [Extent1].[No] AS [No], 
  11.         [Extent1].[HireDate] AS [HireDate], 
  12.         [Extent1].[Name] AS [Name], 
  13.         [Extent2].[PayYear] AS [PayYear], 
  14.         [Extent2].[PayMonth] AS [PayMonth], 
  15.         [Extent2].[bonus] AS [bonus], 
  16.         1 AS [C1]
  17.         FROM  [dbo].[Employee] AS [Extent1]
  18.         LEFT OUTER JOIN [dbo].[EmployeeSalary] AS [Extent2] ON [Extent1].[No] = [Extent2].[EmpNo]
  19.     )  AS [Project1]
  20.     ORDER BY [Project1].[No] ASC

以上 One-To-Many的EntityFramework 6 讀取方式,完整介紹完畢,希望對讀取有所幫忙

2014年10月29日 星期三

Entity Framework 實戰 - Table Per Hierarchy Inheritance (TPH)實作

      今天我想抽空來寫篇關於 .Net EntityFramework 與 資料庫單一資料表(Table)的實作,這次實作機制方法為 Table Per Hierarchy Inheritance(TPH),顧名思義就是在底層資料庫的一個資料表對應了程式的資料模型多個實體,
我直接舉個例子來解釋資料庫與領域模型間的圖型。

資料庫 Table 圖例

然而在系統設計時,領域模型我們採取了一下設計


在上圖系統領域模型中, Media 為父類別 (Parent Class) ,而 Article 與 Video、Photo皆為繼承 Media 父類別的子類別(Child Class)


PS.注意,在 Media 類別,並沒有 Media 資料表的欄位 MediaType , 而 MediaType欄位的值在資料表是用來識別被繼承的子類別是屬於那個型別,
如 MediaType = "Article" , 此時代表為 Article Class ,依次為 MediaType = "Video" 代表為 Video Class ; MediaType = "Photo" 代表為 Photo Class 。

現在我開始撰寫 Media 、Article 、Video、Photo Class Code


因為 我採用 Code-First 的方式去實作 EntityFramework ,所以底下我設計一個 DBEntities Class ,並讓它繼承了 DbContext ,
這樣後續我就可以透過 DBEntitis 去處理後續的實體增修 CRUD。

上述步驟都完成後,接下來可以來測試透過 DBEntities 來進行新增并實際寫入資料表。
在這邊我利用 Windows Form 當做前端界面來實作


而在 寫入(存檔)的  Button  ,我寫了以下程式
    1:          private void button1_Click(object sender, EventArgs e)  
    2:         {  
    3:             //進行存檔
    4:             using(var context = new DBEntities())  
    5:             {  
    6:                 Article article = new Article() { Title = "網智數位行銷手冊秘笈", MediaID = "001" };  
    7:                 context.Media.Add(article);  
    8:   
    9:                 Video video = new Video() { Title = "網智ERP教學影片", MediaID = "002" };  
   10:                 context.Media.Add(video);  
   11:   
   12:                 Photo photo = new Photo() { Title = "網智數位設計", MediaID = "003" };  
   13:                 context.Media.Add(photo);  
   14:   
   15:                 context.SaveChanges();  
   16:   
   17:             }  
   18:         }  

點擊 寫入(存檔)Button後,此時在去後端資料庫檢查,我們可以看到結果如下

此時,資料表正確無誤的寫入 3 筆資料列,並且 MediaType 欄位,也會自動寫入對應的值(Article、Video、Photo)。




網智數位-軟體開發


2014年4月16日 星期三

.NET LINQ 查詢太陽花水果

下午我在開發公司的產品系統,遇到一些 LINQ Lamba 動態查詢的需求(這個議題,我擇天會寫一篇專文介紹),所以先介紹一下LINQ Query,作為.NET程式設計師(不論是寫C#或VB)都應該知道LINQ查詢語言,而它也是我開發.NET數年最愛的技術之一,因為它的各種內部演算法都已由微軟實作好,通常我都會用 Lambd Expression 或 LINQ Query,如以下語法:
我們先建立 水果清單 …
有 香蕉、蘋果、芒果、香瓜、太陽花(今年台灣的名產)
   1: //建立水果清單



   2:            List<Fruit> Fruits = new List<Fruit>() 



   3:            { new Fruit { Id = 1, Name = "香蕉", Desc = "香蕉" }



   4:            , new Fruit { Id = 2, Name = "蘋果", Desc = "蘋果" }



   5:            , new Fruit { Id = 3, Name = "芒果", Desc = "芒果" }



   6:            , new Fruit { Id = 4, Name = "香瓜", Desc = "香瓜"}



   7:            , new Fruit { Id = 5, Name = "太陽花", Desc = "太陽花,是香蕉的一種^^"}



   8:            };




如果我想找出水果名有 “果”字的,我會用以下兩種方式

第一種 Lamba Expression


   1: //第一種 Lamba Expression



   2: var fruitResult1 = Fruits.Where(t => t.Name.Contains("果"));



第二種,LINQ Query (類似 SQL Style)

   1: //第二種,LINQ Query (類似 SQL Style)



   2:      var fruitResult2 = (from f in Fruits



   3:                          where f.Name.Contains("果")



   4:                          select f);




我們把結果列印至營幕


   1: //找出水果名有 “果”字的,我會用以下兩種方式



   2:           //第一種 Lamba Expression



   3:           var fruitResult1 = Fruits.Where(t => t.Name.Contains("果"));



   4:  



   5:           //Print search result to screen



   6:           Console.WriteLine("第一種 Lamba Expression");



   7:           foreach (Fruit fruit in fruitResult1)



   8:               Console.WriteLine(fruit.Name);



   9:  



  10:           //第二種,LINQ Query (類似 SQL Style)



  11:           var fruitResult2 = (from f in Fruits



  12:                               where f.Name.Contains("果")



  13:                               select f);



  14:  



  15:           Console.WriteLine();



  16:  



  17:           //Print search result to screen



  18:           Console.WriteLine("第二種,LINQ Query (類似 SQL Style)");



  19:           foreach (Fruit fruit in fruitResult2)



  20:               Console.WriteLine(fruit.Name);



  21:  



  22:           //Wait press any key



  23:           Console.ReadLine();




image


這樣很快的得到我們要的正確結果。


那麼如果有找出太陽花水果呢?


…..各位知道如何寫這段查詢語法吧?




   1: var fruitResult3 = Fruits.Where(t => t.Desc.Contains("太陽花"));



   2:           Console.WriteLine(" 查詢結果。。。今天程式寫累了。。");



   3:           foreach (Fruit fruit in fruitResult3)



   4:               Console.WriteLine(fruit.Name);



image