首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Visual Studio 2010 實戰:Entity Framework 4.0 與 WCF Data Services 4.0 聯手打造部落格系統

     編輯:關於.NET

前言:模型優先、POCO、OData 的三重奏

VS 2010 帶來 EF 4.0 (Model-First、FK、Lazy Loading、T4、POCO) 與 WCF Data Services 4.0 (OData 協議、雙向綁定、分頁、行計數、投影、Blob)。本文以 MyBlog 為例:ASP.NET 前台唯讀瀏覽 + Silverlight 後台編輯,示範從建模到部署的完整流程。

EF 4.0 核心新功能實戰

1. Model-First:從畫圖到資料庫

  • 新增 ADO.NET Entity Data Model → 選 Empty Model。
  • 工具箱拖拉 Entity,右鍵 Add → Scalar Property 建立 Blog/Post/Tag 三實體 (圖 1)。
  • 右鍵設計面 Add → Association 建立關聯,EF 4.0 自動產生 FK 欄位 BlogBlogID (圖 2)。
  • 右鍵 Generate Database from Model → 建立空 DB → 執行產生的 .edmx.sql 完成建表 (圖 3-4)。

2. T4 自定義代碼生成

  • 右鍵 Add Code Generation Item → 選 ADO.NET EntityObject Generator (Model1.tt)。
  • 原 .Designer.cs 代碼移至 Model1.cs,修改 .tt 即時重新生成,極大提升擴充彈性。

3. POCO 實體:擺脫基類束縛

  • 模型屬性 Code Generation Strategy = None,刪除 .tt。
  • 手寫純類別 (圖 6-8):Blog/Post/Tag 僅含自動屬性與導航集合。
  • 自訂 BlogContext : ObjectContext (圖 9),以 CreateObjectSet<T>() 暴露 ObjectSet<T>。

4. Lazy Loading:虛擬屬性一鍵開啟


// Blog.cs / Tag.cs
public virtual List Posts { get; set; }
// Post.cs
public virtual List Tags { get; set; }

EF 運行時代理自動攔截屬性存取觸發載入。注意:WCF Data Services 序列化會觸發遞迴載入,本範例故關閉 Lazy Loading 改用 .Expand() 顯式載入。

WCF Data Services 4.0 服務端建置

1. 新增服務與權限配置


public class BlogService : DataService
{
    public static void InitializeService(DataServiceConfiguration config)
    {
        config.SetEntitySetAccessRule("Blogs", EntitySetRights.All);
        config.SetEntitySetAccessRule("Posts", EntitySetRights.All);
        config.SetEntitySetAccessRule("Tags", EntitySetRights.All);
        config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        // 分頁示範
        config.SetEntitySetPageSize("Posts", 5);
    }
}

2. Query Interceptor:依登入用戶過濾資料


// 僅公開公開貼文 或 當前用戶擁有的貼文
[QueryInterceptor("Posts")]
public Expression> OnPostQuery()
    => p => p.Public || p.Blog.Owner == HttpContext.Current.User.Identity.Name;

// 僅當前用戶擁有的部落格
[QueryInterceptor("Blogs")]
public Expression> OnBlogQuery()
    => b => b.Owner == HttpContext.Current.User.Identity.Name;

Silverlight 客戶端串接與新功能展示

1. 啟用 DataServiceCollection (雙向綁定)

編輯 Reference.datasvcmap:



  
  

產生的實體自動實作 INotifyPropertyChanged/INotifyCollectionChanged,可直接綁定 DataGrid/ComboBox。

2. 主頁面邏輯 (MainPage.xaml.cs)


public MainPage()
{
    InitializeComponent();
    _svc = new BlogContext(new Uri("/BlogService.svc", UriKind.Relative));
    _blogs = new DataServiceCollection(_svc);
    LayoutRoot.DataContext = _blogs;

    _blogs.LoadCompleted += Blogs_LoadCompleted;
    _blogs.LoadAsync(_svc.Blogs.Expand("Posts")); // 預載貼文
}

void Blogs_LoadCompleted(object s, LoadCompletedEventArgs e)
{
    if (e.Error == null && _blogs.Count > 0) cboBlogs.SelectedIndex = 0;
}

private void cboBlogs_SelectionChanged(object s, SelectionChangedEventArgs e)
{
    grdPosts.DataContext = cboBlogs.SelectedItem;
    // 行計數示範
    var q = (from p in _svc.Posts.IncludeTotalCount()
             where p.BlogBlogID == ((Blog)cboBlogs.SelectedItem).BlogID
             select p) as DataServiceQuery;
    ((Blog)cboBlogs.SelectedItem).Posts.LoadCompleted += Posts_LoadCompleted;
    ((Blog)cboBlogs.SelectedItem).Posts.LoadAsync(q);
}

void Posts_LoadCompleted(object s, LoadCompletedEventArgs e)
{
    if (e.Error == null)
    {
        int total = e.QueryOperationResponse.TotalCount;
        lblCount.Content = $"Displaying {((Blog)cboBlogs.SelectedItem).Posts.Count} of {total} posts";
    }
}

3. 儲存變更 (批次更新)


private void btnSave_Click(object s, RoutedEventArgs e)
    => _svc.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, _svc);

void OnChangesSaved(IAsyncResult ar)
{
    var ctx = (BlogContext)ar.AsyncState;
    try { ctx.EndSaveChanges(ar); }
    catch (Exception ex) { MessageBox.Show(ex.Message); }
}

4. 伺服器分頁:LoadNextPartialSetAsync


private void btnMorePosts_Click(object s, RoutedEventArgs e)
{
    var blog = (Blog)cboBlogs.SelectedItem;
    blog.Posts.LoadCompleted += Posts_LoadCompleted;
    blog.Posts.LoadNextPartialSetAsync(); // 取得下一頁
}

5. 投影:$select 查詢選項


// URI 形式
/BlogService.svc/Posts?$select=Title,PostContent

// LINQ 形式 (客戶端)
var q = _svc.Posts.Where(p => p.BlogBlogID == id).Select(p => new { p.Title, p.PostContent });

減少頻寬與記憶體佔用,大數據集查詢極具價值。

總結與代碼下載

技術點關鍵 API / 設定商業價值
Model-FirstGenerate Database from Model敏捷建模、DBA 協作
POCOCode Generation Strategy = None領域模型純粹性、可測試性
Lazy Loadingvirtual 導航屬性按需載入、簡化代碼
OData 服務DataService<T> + QueryInterceptor跨平台資料開放、安全控制
雙向綁定UseDataServiceCollection=trueSilverlight/WPF MVVM 無縫體驗
分頁/行計數/投影SetEntitySetPageSize / IncludeTotalCount / $select大數據效能優化

完整原始碼:https://code.msdn.microsoft.com/mag201004VSData

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved