程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 走進Linq-How do I(4)拾遺補零篇第一節

走進Linq-How do I(4)拾遺補零篇第一節

編輯:關於.NET

最近很忙,真的很忙,所以這個系列好久沒更新了,從今天起我又開始了我 的走進Linq之旅。Linq to SQL的用法基本上都說完了,還有一些細枝末節的地 方需要聊聊。

強類型DataContext

在Linq to SQL的第一篇的時候 就說道DataContext是一個入口點,我們使用Linq to SQL做的一些操作幾乎都是 施加在這個類上的。在使用VS的設計器生成的代碼裡,我們會看到一個從 DataContext繼承的局部類,大家都習慣的將這個類稱之為強類型的DataContext ,她對DataContext做了進一步的封裝。

今天我們先就對DataContext一 些沒有介紹過的地方詳細討論一下。

首先我們先手寫一個強類型的 DataContext:

強類型的DataContext
  [Database (Name="CnBlogs")]
  public class CnBlogsDataContext : DataContext
  {
    public CnBlogsDataContext(string fileOrConnectionString)
      : base (fileOrConnectionString)
    { }
    public CnBlogsDataContext(string fileOrConnectionString, MappingSource mapping)
      : base(fileOrConnectionString, mapping)
    { }
    public CnBlogsDataContext(IDbConnection conn)
      : base(conn)
    { }
     public CnBlogsDataContext(IDbConnection conn, MappingSource mapping)
      : base(conn, mapping)
    { }
     public Table<Post> Posts
    {
      get { return this.GetTable<Post>(); }
    }
     public Table<Blog> Blogs
    {
      get { return this.GetTable<Blog>(); }
    }
     public Table<User> Users
    {
      get { return this.GetTable<User>(); }
    }
     [Function(Name = "dbo.GetPostsByBlogId")]
     public ISingleResult<Post> GetPostsByBlogId(
       [Parameter(Name="blogid",DbType="int")]
       int blogid)
    {
      IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo) (MethodInfo.GetCurrentMethod())), blogid);
      return (ISingleResult<Post>)result.ReturnValue;
    }
     [Function(Name = "dbo.GetBblogsOrPosts")]
     [ResultType(typeof(Blog))]
    [ResultType(typeof(Post))]
    public IMultipleResults GetBlogsOrPosts(
       [Parameter(Name = "kind", DbType = "int")]
      int kind)
    {
      IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo) MethodInfo.GetCurrentMethod()), kind);
      return (IMultipleResults)result.ReturnValue;
    }
     [Function(Name = "dbo.GetBblogsAndPosts")]
     [ResultType(typeof(Blog))]
    [ResultType(typeof(Post))]
    public IMultipleResults GetBlogsOrPosts()
    {
      IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)MethodInfo.GetCurrentMethod()));
      return (IMultipleResults)result.ReturnValue;
    }
  }

在這個類裡出現了四個前面沒有看到的特性: Database,Function,Parameter,ResultType至於Database就不用說了,就是做數 據庫映射的。下面對其它三個做一些討論:

Function、Parameter和 ResultType

Linq to SQL不僅僅能做字段與屬性之間的映射,還可以將存 儲過程或用戶自定義方法與.net裡的方法之間做映射,功能是不是很強大?這個 映射就是通過Function和Parameter共同完成的。

Function有兩個屬性 IsComposable和Name,Name就是用來指定數據庫中存儲過程或者用戶自定義方法 的名字,當IsComposable為true的時候,則表明該方法對應著一個用戶自定義方 法,否則對應一個存儲過程,默認是false。Function特性只能放在方法上面。

Parameter就是用來映射存儲過程或方法接受的參數。

還是用例 子來說明:

假設有這樣的一個存儲過程,通過blogid找出其所有的隨筆

ALTER PROCEDURE dbo.GetPostsByBlogId
(
@blogid int
)
AS
SELECT postid,blogid,title,body,createdate FROM posts WHERE blogid = @blogid
RETURN

我要在.net裡寫一個方法來對應這個存儲過程

[Function(Name = "dbo.GetPostsByBlogId")]
public ISingleResult<Post> GetPostsByBlogId(
[Parameter(Name="blogid",DbType="int")]
int blogid)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), blogid);
return (ISingleResult<Post>)result.ReturnValue;
}

現在你可以以調用.net方法的形式直接調用這個方法來調用存儲 過程

ISingleResult<Post> posts = dbCtx.GetPostsByBlogId(1);
foreach (var p in posts)
{
Console.WriteLine(p.Title);
}

這樣就將存儲過程封裝成.NET的方法了,調用看看:

使用存儲過程的時候,我們往往使用一個條件參數,根據條件參數的 不同返回不同的結果集:

ALTER PROCEDURE dbo.GetBblogsOrPosts
(
@kind int,
)
AS
if @kind = 1
SELECT * FROM blogs
ELSE
SELECT * FROM posts
RETURN

在.NET裡使用這樣的方法映射:

[Function(Name = "dbo.GetBblogsOrPosts")]
[ResultType(typeof(Blog))]
[ResultType(typeof(Post))]
public IMultipleResults GetBlogsOrPosts(
[Parameter(Name = "kind", DbType = "int")]
int kind)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)MethodInfo.GetCurrentMethod()), kind);
return (IMultipleResults)result.ReturnValue;
}

返回 一個ImultipleResults對象,該對象有一個GetResult方法:

IMultipleResults results = dbCtx.GetBlogsOrPosts(1);
foreach (var b in results.GetResult<Blog>())
{
Console.WriteLine(b.Name;
}

除了支持這種存儲過程外, 還支持這樣的:

CREATE PROCEDURE dbo.GetBblogsAndPosts
AS
SELECT * FROM blogs
SELECT * FROM posts
RETURN

使用方法還是和上面的一樣。

在DataContext還有 幾個我們比較感興趣的方法:

ExecuteCommand, ExecuteQuery<TResult>,Translate

這幾個方法都是為了 和傳統的ADO.NET集成的。

ExecuteCommand可以做insert,update,delete 操作,第一個參數接受一個格式化的sql語句,第二個參數是參數數組:

使用起來很簡單:

dbCtx.ExecuteCommand("insert into posts (blogid,title,body) values({0},{1},{2})", "2", "走 進Linq-How do I(4)", "廢話一篇");

ExecuteQuery<TResult>方法呢?顧名思義,就是執行查詢的, 也有兩個參數,第一個接受查詢的SQL語句,第二個接受參數,返回一個 IEnumerable<T>對象:

IEnumerable<Post> posts = dbCtx.ExecuteQuery<Post>("select * from posts where postid = {0}", "1");
      foreach (var post in posts)
        Console.WriteLine (post.Title);

Translate方法是將以前的DataReader轉換為現在 的Linq to SQL方式,這樣有什麼好處呢:

1.可以利用現在的映射,不再 需要這樣的語句post.Title = dr[1].ToString();

2.可以使用查詢表達 式的語法

對於插入,更新,刪除這些經常使用的操作,為了提高性能, 或者做一些自定義的操作,你還可以覆蓋微軟默認為你提供的Insert,Update等 方法:

1.寫一個存儲過程

CREATE PROCEDURE dbo.CreatePost
(
@blogid int,
@title nvarchar(50),
@body nvarchar(500)
    )
AS
insert into posts (blogid,title,body) values(@blogid,@title,@body)
RETURN

當然,這個存儲過程非常簡單,不值得這麼去做,你就 假設存在一個復雜的存儲過程

2.把Posts表拖到設計器上,上面的存儲過 程拖到方法設計器上

3.右鍵點擊設計器上的表,在右鍵菜單裡會有一項 :配置行為(Config Behavior):

這樣就可以用你自定義的存儲過程做插入操作了。

Linq to SQL中的事務

事務這個東西在並發的時候特別重要,Linq to SQL本身就 支持事務,不過是樂觀鎖。我們也可以顯式的啟動Linq to SQL的事務。

dbCtx.Transaction = dbCtx.Connection.BeginTransaction ();
      try
      {
         dbCtx.ExecuteCommand("insert into posts(blogid,title,body) values({0},{1},{2})", "2", "走進Linq-How do I(4) ", "廢話一篇");
         dbCtx.ExecuteCommand("insert into posts(blogid,title,body) values({0},{1},{2})", "3", "走進Linq-How do I(5) ", "廢話兩篇");
         dbCtx.Transaction.Commit();
      }
       catch
      {
         dbCtx.Transaction.Rollback();
      }

DbConnection的BeginTransaction方法還可以接受一個枚舉參數 IsolationLevel,來指定事務隔離的級別。

對於那些多個DataContext之 間的事務,我們可以使用.NET 2.0引入的TransactionScope

下一篇談談 RowVersion的問題

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved