Mini ORM——PetaPoco筆記

記錄一下petapoco官網博客的一些要點。這些博客記錄了PetaPoco是如何一步步改進的。mysql

第一個版本。git

PetaPoco-Improvementsgithub

http://www.toptensoftware.com/Articles/69/PetaPoco-Improvementsweb

若是運行查詢時不以「select」開頭,則petapoco會自動加上:sql

// Get a record
var a=db.SingleOrDefault<article>("SELECT * FROM articles WHERE article_id=@0", 123);


// can be shortened to this: Get a record
var a=db.SingleOrDefault<article>("WHERE article_id=@0", 123);

增長了IsNew和Save方法:數據庫

若是如今有一個poco對象,要確認它是否在數據庫中仍是一個新記錄,能夠經過檢查它的主鍵是否被設置了默認值之外的值來判斷:數組

// Is this a new record 
if (db.IsNew(a))
{
    // Yes it is...
}

相關的,有一個Save方法,來自動決定是插入記錄仍是更新記錄:緩存

// Save a new or existing record
db.Save(a);

PetaPoco-Improvements II多線程

http://www.toptensoftware.com/Articles/70/PetaPoco-Improvements-II架構

改進列映射:PetaPoco支持[Ignore]屬性來指定某個屬性被忽略,如今添加了兩個新屬性:

[ExplicitColumns]:添加到POCO類來表示只有明確標出的列才進行映射

[Column]:添加到全部須要映射的列

緩存POCO類型信息

跟蹤最後一個SQL語句:公開了三個參數:

LastSQL

LastArgs:一個Object[]數組傳遞的全部參數

LastCommand:一個字符串,顯示SQL和參數

能夠在調試監視窗口監視LastCommand屬性。

異常處理:經過OnException方法來找出錯誤

一些錯誤:

Fetch方法返回一個List,而不是一個IEnumerable。

有些方法使用默認參數,沒法與舊版本C#兼容。

自動Select沒法檢測到以空白開始的select語句。

MySQL參數管理和用戶自定義鏈接字符串不能正常工做。

PetaPoco-T4 Template

http://www.toptensoftware.com/Articles/71/PetaPoco-T4-Template

增長了T4模板支持:

自動生成PetaPoco對象:

[TableName("articles")]
[PrimaryKey("article_id")]
[ExplicitColumns]
public partial class article  
{
    [Column] public long article_id { get; set; }
    [Column] public long site_id { get; set; }
    [Column] public long user_id { get; set; }
    [Column] public DateTime? date_created { get; set; }
    [Column] public string title { get; set; }
    [Column] public string content { get; set; }
    [Column] public bool draft { get; set; }
    [Column] public long local_article_id { get; set; }
    [Column] public long? wip_article_id { get; set; }
}

還能夠生成一些經常使用方法,好比Save(),IsNew(),Update(),SingleOrDefault()...能夠這樣使用:

var a = article.SingleOrDefault("WHERE article_id=@0", id);
a.Save();

T4模板從PetaPoco.Database推導出一個類來描述數據庫自己,這個類有一個靜態方法GetInstance(),能夠用這個方法來獲得數據庫的實例,這樣來使用:

var records=jabDB.GetInstance().ExecuteScalar<long>("SELECT COUNT(*) FROM articles");

T4模板包括三個文件:

PetaPoco.Core.ttinclude:包括全部讀取數據庫架構的常規方法

PetaPoco.Generator.ttinclude:定義生成內容的實際模板

Records.tt:模板自己,包括一些設置,包括其餘兩個模板文件

一個Records.tt文件看起來是這樣的:

<#@ include file="PetaPoco.Core.ttinclude" #>
<#
    // Settings
    ConnectionStringName = "jab";
    Namespace = ConnectionStringName;
    DatabaseName = ConnectionStringName;
    string RepoName = DatabaseName + "DB";
    bool GenerateOperations = true;

    // Load tables
    var tables = LoadTables();

#>
<#@ include file="PetaPoco.Generator.ttinclude" #>

使用模板:

添加這三個文件到C#項目。

確認在app.config或web.config裏定義了數據庫鏈接字符串connection string and provider name

編輯Records.tt裏的ConnectionStringName爲實際的ConnectionStringName

保存Records.tt文件。T4模板會自動生成Records.cs文件,從數據庫中全部的表來生成POCO對象。

PetaPoco-NuGet Package

http://www.toptensoftware.com/Articles/73/PetaPoco-NuGet-Package

如今能夠從NuGet來安裝了。

PetaPoco-Paged Queries

http://www.toptensoftware.com/Articles/74/PetaPoco-Paged-Queries

支持分頁查詢,經過FetchPage方法:

public PagedFetch<T> FetchPage<T>(long page, long itemsPerPage, string sql, params object[] args) where T : new()

注意一點page參數是從0開始。返回值是一個PagedFetch對象:

// Results from paged request
public class PagedFetch<T> where T:new()
{
    public long CurrentPage { get; set; }
    public long ItemsPerPage { get; set; }
    public long TotalPages { get; set; }
    public long TotalItems { get; set; }
    public List<T> Items { get; set; }
}

CurrentPage和ItemsPerPage只是反映傳遞過來的page和itemsPerPage參數。由於在構造分頁控件的時候須要用到。

注意返回的是一個List 而不是IEnumerable 。在PetaPoco裏這是一個Fetch而不是一個Query。添加一個IEnumerable版本也很簡單,但考慮到結果集的大小是分頁決定的,所以不必添加。

背後的故事:

我老是以爲構建分頁查詢語句很乏味,這通常涉及到兩個不一樣但很相似的SQL語句:

1.分頁查詢自己

2.查詢全部記錄數量。

接下來說到如何處理MySQL和SQL Server分頁查詢的異同,爲了支持不一樣的數據庫,使用了不一樣的查詢語句。略過。

PetaPoco-Named Columns,Result Columns and int/long conversion

http://www.toptensoftware.com/Articles/75/PetaPoco-Named-Columns-Result-Columns-and-int-long-conversion

命名列:

如今能夠修改映射的列名稱,經過給[Column]屬性一個參數:

[PetaPoco.Column("article_id")] long id { get; set; }

注意,表的[PrimaryKey]屬性和其餘PetaPoco.Database 方法的primaryKeyName參數指的是列名,不是映射的屬性名。

結果列:

有時候運行查詢不只返回表中的列,還會有計算或鏈接的列。咱們須要查詢結果可以填充這些列,但在Update和Insert操做的時候忽略它們。

爲此目的增長了一個新的[ResultColumn]屬性。

假設你有一個categories表,你想可以檢索每一個類別的文章數量。

[TableName("categories")]
[PrimaryKey("category_id")]
[ExplicitColumns]
public class category
{
    [Column] public long category_id { get; set; }
    [Column] public string name { get; set; }
    [ResultColumn] public long article_count { get; set; }
}

你仍然能夠像之前同樣執行Update和Insert方法,aritical_count屬性將被忽略。

var c =  db.SingleOrDefault<category>("WHERE name=@0", "somecat");
c.name="newname";
db.Save(c);

可是你也能夠用它來捕獲join的結果:

var sql = new PetaPoco.Sql()
    .Append("SELECT categories.*, COUNT(article_id) as article_count")
    .Append("FROM categories")
    .Append("JOIN article_categories ON article_categories.category_id = categories.category_id")
    .Append("GROUP BY article_categories.category_id")
    .Append("ORDER BY categories.name");

foreach (var c in db.Fetch<category>(sql))
{
    Console.WriteLine("{0}\t{1}\t{2}", c.category_id, c.article_count, c.name);
}

注意,填充一個[ResultColumn]你必須在你的select字句中顯式引用它。PetaPoco從自動生成的select語句中生成的列中不會包括它們(好比在上一個例子中的SingleOrDefault命令)。

自動long/int轉換

MySQL返回的count(*)是一個long,可是有時候把這個屬性聲明爲int更好些。這將在試圖定義這個屬性的時候致使異常。

如今PetaPoco能夠自動作這個轉換。當long轉換爲int的時候若是值超出範圍則拋出一個異常。

IDataReaders銷燬

上一個版本有個bug,Fetch或Query方法後data readers沒有被銷燬。如今已經修復了這個錯誤。

PetaPoco-NUnit Test Cases

http://www.toptensoftware.com/Articles/76/PetaPoco-NUnit-Test-Cases

若是要在生產環境中使用PetaPoco,很須要可以在一個更可控的方式中進行測試。

爲了可以用相同的一組測試來測試SQL Server和MySQL,設置了兩個鏈接字符串:"mysql"和"sqlserver",而後把這些字符串當作參數來運行測試。

[TestFixture("sqlserver")]
[TestFixture("mysql")]
public class Tests : AssertionHelper
{

數據庫不須要任何特殊的方式配置測試用例好比建立一個名爲petapoco的表而後進行清理工做。有一個嵌入式的SQL資源腳原本進行初始化和清理.

測試用例自己簡單直接的使用每一個特性。對SQL builder功能來講也有測試用例。

主要測試均可以經過,沒有任何問題。有幾個預期的SQL Server的bug已經被修正(好比FetchPage方法有一些SQL語法錯誤和一些類型轉換問題)。

測試用例包含在github庫,但NuGet包中沒有。

PetaPoco-Value Conversions and UTC Times

http://www.toptensoftware.com/Articles/84/PetaPoco-Value-Conversions-and-UTC-Times

這篇文章已通過時了。

PetaPoco-T4 Template support for SQL Server

http://www.toptensoftware.com/Articles/78/PetaPoco-T4-Template-support-for-SQL-Server

增長了支持SQL Server的T4模板。

Some Minor PetaPoco Improvements

http://www.toptensoftware.com/Articles/89/Some-Minor-PetaPoco-Improvements

一些小的改進,讓分頁請求更加容易。

在使用時老是忘掉FetchPage仍是PagedFetch的返回類型。如今統一分頁方法和返回類型,如今都叫作Page。

接受Adam Schroder的建議,page number從1開始比從0開始更有意義。

之前的用法是這樣:

PagedFetch<user> m = user.FetchPage(page - 1, 30, "ORDER BY display_name");

如今這樣用:

Page<user> m = user.Page(page, 30, "ORDER BY display_name");

同時接受Adam Schroder的建議,如今有一個構造函數,接受一個connection string name和provider name做爲參數。

PetaPoco-Transaction Bug and Named Parameter Improvements

http://www.toptensoftware.com/Articles/90/PetaPoco-Transaction-Bug-and-Named-Parameter-Improvements

我剛注意到(已經修復)PetaPoco的支持事務中的bug,並對Database類增長了命名參數的支持。

PetaPoco的Sql builder一直支持命名參數的參數屬性:

sql.Append("WHERE name=@name", new { name="petapoco" } );

如今Database類也支持這個功能了:

var a=db.SingleOrDefault<person>("WHERE name=@name", new { name="petapoco" } );
PetaPoco-Custom mapping with the Mapper interface

http://www.toptensoftware.com/Articles/92/PetaPoco-Custom-mapping-with-the-Mapper-interface

使用Mapper接口自定義映射

最簡單的使用PetaPoco的方法是用聲明哪些屬性應該被映射到哪些列的屬性裝飾你的POCO對象。有時候,這不太實際或有些人以爲這太有侵入性了。因此我添加了一個聲明這些綁定的方法。

PetaPoco.Database類如今支持一個叫作Mapper的靜態屬性,經過它你可使用本身的列和表的映射信息。

首先,你須要提供一個PetaPoco.IMapper接口的實現:

public interface IMapper
{
    void GetTableInfo(Type t, ref string tableName, ref string primaryKey);
    bool MapPropertyToColumn(PropertyInfo pi, ref string columnName, ref bool resultColumn);
}

當GetTableInfo方法被調用時,tableName和primaryKey將被設置爲PetaPoco定義的默認值,若是你須要其餘的,修改便可,記得首先檢查類型。

相似的,MapPropertyToColumn方法-修改columnName和resultColumn的值來適應你的須要。容許映射返回true,或忽略它返回false。

一旦你實現了IMapper接口,你只須要設置PetaPoco的靜態屬性Mapper:

PetaPoco.Database.Mapper = new MyMapper();

注意這有一些限制,不過我以爲這是值得的。

一、這個mapper是被全部Database的實例共享的。PetaPoco在全局緩存這些列映射,因此不能爲不一樣的數據庫實例提供不一樣的映射。

二、只能安裝一個mapper。

PetaPoco-Smart Consecutive Clause Handling in SQL Builder

http://www.toptensoftware.com/Articles/91/PetaPoco-Smart-Consecutive-Clause-Handling-in-SQL-Builder

有時須要添加多個可選的Where字句。PetaPoco的連續子句處理能夠自動正確加入它們。

想象一下,你正在查詢一個數據庫,有兩個可選條件,一個開始日期,一個結束日期:

List<article> GetArticles(DateTime? start, DateTime? end)
{
    var sql=new Sql();

    if (start.HasValue)
        sql.Append("WHERE start_date>=@0", start.Value);

    if (end.HasValue)
    {
        if (start.HasValue)
            sql.Append("AND end_date<=@0", end.value);
        else
            sql.Append("WHERE end_data<@0", end.Value);
    }

    return article.Fetch(sql);
}

計算第二個條件是where仍是and子句很乏味。如今PetaPoco能夠自動檢測連續的where子句並自動轉換後續的爲and子句。

List<article> GetArticles(DateTime? start, DateTime? end)
{
    var sql=new Sql();

    if (start.HasValue)
        sql.Append("WHERE start_date>=@0", start.Value);

    if (end.HasValue)
        sql.Append("WHERE end_data<@0", end.Value);

    return article.Fetch(sql);
}

有一些注意事項,但很容易處理。

一、where子句必須是Sql片斷的第一個部分,因此下面的不會工做:

sql.Append("WHERE condition1 WHERE condition2");

但這樣的能夠:

sql.Append("WHERE condition1").Append("WHERE condition2");

二、Sql片斷必須相鄰,因此這樣的不會工做:

sql.Append("WHERE condition1").Append("OR condition2").Append("WHERE condition3");

三、你也許須要給個別條件加上括號來確保獲得正確的優先級:

sql.Append("WHERE x");
sql.Append("WHERE y OR Z");

應該寫成:

sql.Append("WHERE x");
sql.Append("WHERE (y OR z)");

這個功能也適用於Order By子句:

var sql=new Sql();
sql.Append("ORDER BY date");
sql.Append("ORDER BY name");

將生成:

ORDER BY date, name

PetaPoco-Performance Improvements using DynamicMethods

http://www.toptensoftware.com/Articles/93/PetaPoco-Performance-Improvements-using-DynamicMethods

使用動態方法的性能改進

PetaPoco已經比典型的Linq實現快。經過消除反射用動態生成的方法取代它,如今甚至更快-約20%。

在原始版本,PetaPoco一直使用反射來設置它建立的從數據庫中讀取的POCO對象的屬性。反射的優點是很容易使用,不足之處是有一點點慢。

在.NET裏可使用DynamicMethod和ILGenerator動態生成一段代碼。這是至關複雜的實現,須要瞭解MSIL。但它的速度更快,約20%。事實上我但願性能可以更好,因此也許不應給反射扣上速度慢的壞名聲。

因此這裏的想法很簡單-使用一個IDataReader並動態生成一個函數,它知道如何從data reader中讀取列值,並直接將它們分配給POCO相應的屬性。

爲了實現此目的,我作了一個公開可見的變化-即virtual Database。ConvertValue方法已廢棄,在IMapper接口使用一個新的GetValueConverter方法替代之。

public interface IMapper
{
    void GetTableInfo(Type t, ref string tableName, ref string primaryKey);
    bool MapPropertyToColumn(PropertyInfo pi, ref string columnName, ref bool resultColumn);
    Func<object, object> GetValueConverter(PropertyInfo pi, Type SourceType);
}

這麼作的主要目的是,提供了一個能夠在生成MSIL的時候採用的決策點。若是一個converter是調用它的MSIL須要的,則生成。若是不則省略。

添加動態方法生成增長了一些成本,.cs文件大小增長了120行左右。但我認爲值得。

PetaPoco-More Speed

http://www.toptensoftware.com/Articles/94/PetaPoco-More-Speed

我注意到Sam Saffron的Dapper項目……(Dapper也是一個很好的微型ORM框架)

首先我忘了昨天的帖子中提到的DynamicMethod支持的想法來自Sam Saffron在Stack Overflow上發表的帖子,如何壓榨更多的性能。

其次,Sam Saffron開源了Dapper項目,包括一個比較各類ORM的基準測試程序。固然我忍不住更新它來支持PetaPoco,很快就突破了幾個小瓶頸。一點點小調整,這是一些典型結果(就是說PetaPoco很快,確定比EF快了):

運行500次迭代載入一個帖子實體
手工編碼 65ms
PetaPoco(Fast) 67ms
PetaPoco(Normal) 78ms
Linq 2 SQL 841ms
EF 1286ms
我運行了PetaPoco的兩個測試模式,Normal和Fast

Normal - 全部的默認選項和啓用smarts

Fast - 全部的smarts,好比自動select子句,強制DateTime到UTC轉換,命名參數等都禁用

Normal模式是我很指望一般使用PetaPoco的方式,但禁用這些額外功能一直是可選的,當你真的試圖壓榨全部的性能的時候。

共享鏈接支持

主要的修復是能夠重用一個單一數據庫鏈接。在以前的版本中每一個查詢都會致使一個新的鏈接。經過公開OpenSharedConnection方法,你能夠預先調用它,全部隨後的查詢都將重用相同的鏈接。調用OpenSharedConnection和CloseSharedConnection是引用計數(reference counted),能夠嵌套。

爲一個HTTP請求的持續時間打開共享鏈接可能會是一個好主意。我尚未嘗試,but I going to try hooking this in with StructureMap's HttpContextScoped .

最後關於共享鏈接要注意的。PetaPoco一旦被銷燬會自動關閉共享鏈接。這意味着,若是調用OpenSharedConnection一次,and the Database is disposed everything should be cleaned up properly。

其餘可選行爲:

其餘功能是禁止一些PetaPoco行爲的能力:

-EnableAutoSelect,是否自動添加select子句,禁用時,如下沒法運行:

var a=db.SingleOrDefault<article>("WHERE article_id=@0", id);

-EnableNamedParams,是否處理Database類的參數,禁用時,如下沒法運行:

var a=db.SingleOrDefault<article>("WHERE article_id=@id", new { id=123 } );

-ForceDateTimesToUtc,禁用時,日期時間會返回數據庫提供的徹底相同的數據。啓用時,PetaPoco返回DateTimeKind.Utc類型。

禁用這些特性能夠帶來一點小的性能提高。若是他們形成了一些不良影響也提供了可能性來繞過這些特性。

其餘優化

還作了一些其餘的優化:

First(), FirstOrDefault(), Single() and SingleOrDefault()這些方法基準測試程序並不使用,單我仍是提供了優化版本,返回一個記錄,保存創建一個列表,或單條記錄的enumerable。

用try/finally來代理using子句,PetaPoco內部使用一個可清理對象和using語句來確保鏈接被關閉。我已經更換了這些,用一個直接調用和finally塊來保存實例化一個額外的對象。

Benchmarking SubSonic's Slow Performance

http://www.toptensoftware.com/Articles/95/Benchmarking-SubSonic-s-Slow-Performance

本文主要是說Subsonic性能如何慢,以SingleOrDefault方法爲例。

PetaPoco - Support for SQL Server Compact Edition

http://www.toptensoftware.com/Articles/96/PetaPoco-Support-for-SQL-Server-Compact-Edition

支持SQL Server Compact版本。略過。

PetaPoco - PostgreSQL Support and More Improvements

http://www.toptensoftware.com/Articles/98/PetaPoco-PostgreSQL-Support-and-More-Improvements

支持PostgreSQL數據庫。略過。

PetaPoco - A couple of little tweaks

http://www.toptensoftware.com/Articles/99/PetaPoco-A-couple-of-little-tweaks

幾個小調整。

Sql.Builder

爲了使Sql.Builder更流暢,添加了一個新的靜態屬性返回一個Sql實例。之前寫法:

new Sql().Append("SELECT * FROM whatever");

如今寫法:

Sql.Builder.Append("SELECT * FROM _whatever");

這是一個微不足道的變換,但可讀性更好。

自動Select子句改進

此前,PetaPoco能夠自動轉換:

var a = db.SingleOrDefault<article>("WHERE id=@0", 123);

轉換爲:

var a = db.SingleOrDefault<article>("SELECT col1, col2, col3 FROM articles WHERE id=@0", 123);

如今它也會處理這個問題:

var a = db.SingleOrDefault<article>("FROM whatever WHERE id=@0", 123);

換言之,若是它看到一個語句以FROM開始,它只添加SELECT語句和列名列表,而不添加FROM子句。

T4模板改進

因爲NuGet的奇怪的特性,安裝文件順序爲字母倒序排列。致使T4模板在必須的文件以前安裝,隨之而來一堆錯誤。根據David Ebbo的建議Record.tt更名爲Database.tt。

PetaPoco - Working with Joins

http://www.toptensoftware.com/Articles/101/PetaPoco-Working-with-Joins

一般狀況下,使用PetaPoco有一個至關直接的映射,從C#類映射到數據庫。大部分時間這工做的很好,可是當你須要一個JOIN時-你須要比C#類的屬性更多的列來保存。

方法1-手動定義一個新的POCO類

第一個方法是簡單的建立一個新類來保存全部的JOIN後的列。好比須要一個文章標題列表和每篇文章的評論計數,SQL看起來像這樣:

SELECT articles.title, COUNT(comments.comment_id) as comment_count
FROM articles
LEFT JOIN comments ON comments.article_id = articles.article_id
GROUP BY articles.article_id;

定義一個C#類來保存結果(注意屬性名稱匹配SQL的列名)

public class ArticleWithCommentCount
{
    public string title 
    { 
        get; 
        set; 
    }

    public long comment_count
    {
        get;
        set;
    }
}

使用新類型來查詢:

var articles = db.Fetch<ArticleWithCommentCount>(sql);

方法2-擴展示有的POCO對象

更有可能的是你已經有了一個POCO對象,包括了JOIN結果的大部分列,你只是想加入額外的幾個列。

與上個例子相同,你已經有了一個article對象,你只是想加入一個comment_count屬性,這就須要[ResultColumn]屬性了,添加一個新屬性到現有的類:

[ResultColumn]
public long comment_count
{
    get;
    set;
}

經過聲明一個屬性爲[ResultColumn],若是結果集的列名匹配它將被自動填充,可是Update和Insert的時候會被忽略。

方法3-擴展T4模板中的POCO對象

上面的方法很好,若是你手動編寫本身的POCO類。可是若是你用T4模板來生成呢?你如何擴展這些類的屬性,從新運行模板不會覆蓋新屬性?答案在於T4模板生成的是partial class。

若是你不知道什麼是partial class……

仍是上面這個例子,添加一個新類,使用與T4模板生成的類相同的名字(確保名稱空間也要匹配)。聲明爲partial class,給任何JOIN的列添加[ResultColumn]屬性:

public partial class article
{
    [ResultColumn]
    public long comment_count
    {
        get;
        set;
    }
}

這是最後生成的查詢(使用PetaPoco的SQL builder)

var articles = db.Fetch<article>(PetaPoco.Sql.Builder
                .Append("SELECT articles.title, COUNT(comments.comment_id) as comment_count")
                .Append("FROM articles")
                .Append("LEFT JOIN comments ON comments.article_id = articles.article_id")
                .Append("GROUP BY articles.article_id")
                );

方法4-對象引用其餘POCO類

固然若是PetaPoco可以使用屬性對象引用來映射JOIN的表會很好-像一個徹底成熟的ORM同樣。但PetaPoco不能這樣作,也許永遠不會-這是不值得的複雜性,這也不是PetaPoco設計用來解決的問題。

更新 方法5-使用C#4.0的dynamic

從最初發布這篇文章以來,PetaPoco已經更新支持C#的dynamic expando objects。這提供了一個偉大的方法來處理JOIN,GROUP BY和其餘計算的查詢。

PetaPoco - Oracle Support and more...

http://www.toptensoftware.com/Articles/103/PetaPoco-Oracle-Support-and-more

Oracle支持。略過

Single和SingleOrDefault的主鍵版本

取一個單一記錄是很簡單的:

var a = db.SingleOrDefault<article>("WHERE article_id=@0", some_id);

固然最多見的狀況是根據主鍵取記錄,因此如今對Single和SingleOrDefault有一個新的重載:

var a = db.SingleOrDefault<article>(some_id);

做爲邊注,不要忘了若是你使用T4模板的話,上面的能夠更簡化:

// Normal version
var a = article.SingleOrDefault("WHERE title=@0", "My Article");

// New simpler PK version
var a = article.SingleOrDefault(some_id);

對於Joins的SQL builder方法

如今增長了兩個新的方法:InnerJoin和LeftJoin:

var sql = Sql.Builder
    .Select("*")
    .From("articles")
    .LeftJoin("comments").On("articles.article_id=comments.article_id");

枚舉屬性類型

此前若是你試圖使用有枚舉屬性的POCO對象會拋出一個異常。如今PetaPoco會正確的轉換整數列到枚舉屬性。

新OnExecutingCommand虛擬方法

OnExecutingCommand是一個新的虛擬方法,在PetaPoco命中數據庫以前被調用。

// Override this to log commands, or modify command before execution
public virtual void OnExecutingCommand(IDbCommand cmd) { }
你在兩種狀況下也許會用到它:

一、日誌-你能夠抓取SQL語句和參數值並記錄任何你須要的。

二、調整SQL-你能夠在返回以前調整SQL語句-也許爲某個特殊平臺的數據庫。

PetaPoco - Not So Poco!(or, adding support for dynamic)

http://www.toptensoftware.com/Articles/104/PetaPoco-Not-So-Poco-or-adding-support-for-dynamic

PetaPoco最初的靈感來自Massive-經過dynamic Expando objects返回一切。對於大多數狀況我以爲這比較麻煩,更喜歡強類型的類。可是有些時候支持dynamic也是有用的-特別是用於Join、Group By和其餘計算查詢時。

構造一個dynamic查詢只需使用現有的查詢方法,只是傳遞一個dynamic的泛型參數。返回的對象將爲每一個查詢返回的列對應一個屬性:

foreach (var a in db.Fetch<dynamic>("SELECT * FROM articles"))
{
    Console.WriteLine("{0} - {1}", a.article_id, a.title);
}

注意此時不支持自動添加SELECT子句,由於PetaPoco不知道表名。

你也能夠作Update、Insert、Delete操做可是你須要指定表名和要更新的主鍵。

// Create a new record
dynamic a = new ExpandoObject();
a.title = "My New Article";

// Insert it
db.Insert("articles", "article_id", a);

// New record ID returned with a new property matching the primary key name
Console.WriteLine("New record @0 inserted", a.article_id")

更新:

// Update
var a = db.Single("SELECT * FROM articles WHERE article_id=@0", id);
a.title="New Title";
db.Update("articles", "article_id", a);
Delete()、Save()和IsNew()方法都相似。

有一個編譯指令,能夠禁用dynamic支持。由於.NET3.5不支持。

PetaPoco - Version 2.1.0

http://www.toptensoftware.com/Articles/105/PetaPoco-Version-2-1-0

支持dynamic

收集了是否應該包括支持dynamic的反饋意見後,我決定採用它。可是若是你運行較早版本的.NET也能夠禁用它。

關閉dynamic支持:

一、打開項目屬性

二、切換到「生成」選項卡

三、在「條件編譯符號」添加PETAPOCO_NO_DYNAMIC

包含空格的列(和其餘非標識符字符的)

之前版本的PetaPoco假設你的數據庫的任何列名都是有效的C#標識符名稱。若是列名中包含空格,固然會出錯,如今已經經過兩種方式來糾正這個錯誤:

一、PetaPoco能夠正確轉義SQL數據庫的分隔符,如[column], column or "column"

二、T4模板清除列名稱以與C#兼容,使用Column屬性來設置列的DB name。

須要注意的是,若是你使用了dynamic的不兼容的列名,PetaPoco在這種狀況下並不試圖糾正它們。你仍將須要修改SQL來返回一個可用的列名。

var a=db.SingleOrDefault<dynamic>(
        "SELECT id, [col with spaces] as col_with_spaces FROM whatever WHERE id=@0", 23); 
Console.WriteLine(a.col_with_spaces);

或者,把返回的Expandos轉換爲dictionary:

var a=db.SingleOrDefault<dynamic>(
        "SELECT id, [col with spaces] FROM whatever WHERE id=@0", 23); 
Console.WriteLine((a as IDictionary<string, object>)["col with spaces"]);

Ansi String支持

DBA專家Rob Sullivan昨天指出,SQL Server在嘗試使用Unicode字符串的參數來查詢數據類型爲varchar的列的索引的時候,會致使嚴重的性能開銷。爲了解決這個問題須要把參數約束爲DbType.AnsiString。如今可使用新的AnsiString類的字符串參數:

var a = db.SingleOrDefault<article>("WHERE title=@0", new PetaPoco.AnsiString("blah"));
Exists(PrimaryKey) and Delete(PrimaryKey)

能夠檢查是否存在一個主鍵的記錄。

if (db.Exists<article>(23)) 
db.Delete <article>(23);

PetaPoco - Incorporating Feedback

http://www.toptensoftware.com/Articles/106/PetaPoco-Incorporating-Feedback

支持無標識的主鍵列

在之前的版本中,PetaPoco假設主鍵列的值老是有數據庫生成和填充。但狀況並不是老是如此。如今PetaPoco的PrimaryKey屬性有了一個新的property - autoIncrement。

[TableName("subscribers")]
[PrimaryKey("email", autoIncrement=false)]
[ExplicitColumns]
public partial class subscribers
{
      [Column] public string email { get; set; }
      [Column] public string name { get; set; }
}

autoIncrement默認設置爲true,你只須要指定不是自動生成主鍵的表便可。當autoIncrement設置爲false的時候PetaPoco能夠正確的插入記錄-忽略主鍵的值而不是試圖取回主鍵。

若是你沒有用這個屬性裝飾,Insert方法還有一個新的重載,可讓你指定是否自動生成主鍵。

public object Insert(string tableName, string primaryKeyName, bool autoIncrement, object poco)

你還能夠經過IMapper來指定這個屬性。由於GetTableInfo方法由於它的ref參數變得有點失控了,我把它改爲這樣:

void GetTableInfo(Type t, TableInfo ti);

public class TableInfo
{
    public string TableName { get; set; }
    public string PrimaryKey { get; set; }
    public bool AutoIncrement { get; set; }
    public string SequenceName { get; set; }
}

不幸的是這是一個不向後兼容的改變。

有一個警告,對全部沒有自增主鍵列的表來講,IsNew()和Save()方法沒法工做,由於沒有辦法知道記錄是否來自數據庫。這種狀況下你應該知道是調用Insert()仍是Update()。

最後,T4模板已經更新爲自動生成autoIncrement屬性。這適用於SQL Server、SQL Server CE、MySQL和PostgreSQL,但不適用於Oracle。

架構調整

PetaPoco的T4模板能夠支持調整在生成最後一個POCO類以前導入的架構信息。這能夠用來重命名或忽略某些表和某些列。

// To ignore a table
tables["tablename"].Ignore = true;

// To change the class name of a table
tables["tablename"].ClassName = "newname";                  

// To ignore a column
tables["tablename"]["columnname"].Ignore = true;            

// To change the property name of a column
tables["tablename"]["columnname"].PropertyName = "newname"; 

// To change the property type of a column
tables["tablename"]["columnname"].PropertyType = "bool";        

// To adjust autoincrement 
tables["tablename"]["columnname"].AutoIncrement = false;

調用LoadTables方法後在Database.tt中使用這個方法。能夠查看最新的Database.tt。

改善存儲過程支持

PetaPoco已經支持存儲過程-你必須關閉EnableAutoSelect讓它在查詢的時候起做用。我已經小小的修正了一下,以便PetaPoco不會在以Execute或Call開頭的語句前自動插入Select子句,這意味着你能夠調用存儲過程:

db.Query<type>("CALL storedproc")     // MySQL stored proc
db.Query<type>("EXECUTE stmt")        // MySQL prepared statement
db.Query<type>("EXECUTE storedproc")  // SQL Server

這只是一個很小的改進,不支持out參數。

T4 Support for SQL Server Geography and Geometry

你能夠添加一個Microsoft.SqlServer.Types.dll引用。

PetaPoco - Single Column Value Requests

http://www.toptensoftware.com/Articles/107/PetaPoco-Single-Column-Value-Requests

單列值查詢

以前的版本只支持返回POCO對象,如今支持這樣的查詢:

foreach (var x in db.Query<long>("SELECT article_id FROM articles"))
{
    Console.WriteLine("Article ID: {0}", x);
}

這能夠支持全部的Type.IsValueType,字符串和byte數組

@字符轉義

PetaPoco使用@ 做爲名稱參數可是可能會和某些Provider衝突。之前你能夠爲MySQL轉義,如今能夠支持全部的Provider了。在這個例子中,@@id將做爲@id傳遞到數據庫中而@name將被用做在傳遞的參數中查找屬性名。(怎麼翻譯?)

select
    t.Id as '@@id'
from
    dbo.MyTable as t
where
    t.Name = @name
for xml path('Item'), root ('Root'), type

Where子句的自動括號

SQL builder能夠自動附加連續的Where子句,好比:

sql.Where("cond1");
sql.Where("cond2");

會變成:

WHERE cond1 AND cond2

這挺好的,可是很容易致使不注意的操做法優先級錯誤。好比:

sql.Where("cond1 OR cond2");
sql.Where("cond3");

會變成:

cond1 OR cond2 AND cond3

老實說我並不知道實際的And和Or的優先級-我也不關心,可是我知道使用SQL builder的Where()方法會致使很容易出現這種問題。因此如今Where()方法會自動給參數加括號,會生成下面的語句:

(cond1 OR cond2) AND (cond3)

注意,這隻適用於Where()方法,當使用Append("WHERE cond")時無效。

PetaPoco - Version 3.0.0

http://www.toptensoftware.com/Articles/108/PetaPoco-Version-3-0-0

本文主要介紹3.0版本的改進,都在前面介紹過了。略過。

PetaPoco-Experimental-Multi-Poco-Queries

http://www.toptensoftware.com/Articles/111/PetaPoco-Experimental-Multi-Poco-Queries

首先這歸功於Sam Saffron的Dapper項目。PetaPoco的多POCO查詢支持與Dapper的很相似但PetaPoco的實現是至關不一樣的,列之間的分割點是不一樣的,它還能夠在POCO對象間自動猜想和分配對象的關係。

背景

多POCO查詢背後的想法是構造一個Join的SQL查詢,從每一個表返回的列能夠自動映射到POCO類。換句話說,不是第一個N列映射到第一個POCO,接下來的N列映射到另外一個……

用法

var sql = PetaPoco.Sql.Builder
                .Append("SELECT articles.*, authors.*")
                .Append("FROM articles")
                .Append("LEFT JOIN users ON articles.user_id = users.user_id");

var result = db.Query<article, user, article>( (a,u)=>{a.user=u; return a }, sql);

一些說明:

一、SQL查詢從兩個表返回列。

二、Query方法的前兩個泛型參數指定了擁有每行數據的POCO的類型。

三、第三個泛型參數是返回集合的類型-通常是第一個表的對象類型,但也能夠是其餘的。

四、Query方法須要它的第一個參數做爲回調委託,能夠用來鏈接兩個對象以前的關係。

因此在這個例子中,咱們返回一個IEnumerable

,每一個article對象都經過它的user屬性擁有一個相關user的引用。

PetaPoco支持最多5個POCO類型,Fetch和Query方法也有變化。

選擇分割點

返回的列必須和Query()方法中的泛型參數的順序相同。好比第一個N列映射到T1,接下來N列映射到T2……

若是一個列名已經被映射到當前POCO類型它就被假定是一個分割點。想象一下這組列:

article_id, title, content, user_id, user_id, name
這些POCO:

class article
{
    long article_id { get; set; }
    string title { get; set; }
    string content { get; set; }
    long user_id { get; set; }
}

class user
{
    long user_id { get; set; }
    string name { get; set; }
}

查詢相似這樣:

db.Query<article, user, article>( ... )

感興趣的是user_id。當映射這個結果集的時候,第一個user_id列將被映射到article,當看到第二個user_id的時候PetaPoco將意識到它已經被映射到article了,因而將其映射到user。

最後一種肯定分割點的方法是當一個列不存在於當前的POCO類型可是存在於下個POCO。注意若是一個列不存在於當前POCO也不存在與下個POCO,它將被忽略。

自動鏈接POCO

PetaPoco能夠在返回對象上自動猜想關係屬性並自動分配對象引用。

這種寫法:

var result = db.Query<article, user, article>( (a,u)=>{a.user=u; return a }, sql);

能夠寫成:

var result = db.Query<article, user>(sql);

兩點須要注意的:

一、第三個返回參數類型不是必需的。返回的結果集合永遠是T1類型。

二、設置對象關係的回調方法不是必需的。

很明顯的,作這項工做PetaPoco有一點小猜想,可是這是一個常見的狀況,我認爲這是值得的。要實現這個目的,T2到T5必需有一個屬性是和它左邊的類型是相同的類型。換句話說:

一、T1必需有一個T2的屬性

二、T1或T2必需有一個T3的屬性

三、T1或T2或T3必需有一個T4的屬性

……

同時,屬性是從右往左搜索的。因此若是T2和T3都有一個T4的屬性,那將使用T3的屬性。

結論和可用性

你可能須要多閱讀這篇文章幾回來理解這個新特性,可是一旦你習慣了我相信你會發現這是一個頗有用的補充。

PetaPoco - What's new in v4.0

http://www.toptensoftware.com/Articles/114/PetaPoco-What-s-new-in-v4-0

使用一個方法代替Transaction屬性

using(var scope = db.Transaction)

改爲這樣:

using(var scope = db.GetTransaction())

多POCO查詢

上一篇文章已經介紹過了。

另外能夠直接調用MultiPocoQuery方法:

IEnumerable<TRet> MultiPocoQuery<TRet>(Type[] types, object cb, string sql, params object[] args)

這個方法接受一個POCO數組做爲參數,而不是泛型參數。

支持IDbParameters做爲SQL arguments

PetaPoco如今支持直接傳遞IDbParameters對象到查詢中。若是PetaPoco沒有正確映射一個屬性的時候這很方便。

例如SQL Server不會將DbNull分配給VarBinary列觸發參數配置了正確的類型。如今能夠這樣作:

databaseQuery.Execute("insert into temp1 (t) values (@0)", 
                new SqlParameter() { SqlDbType = SqlDbType.VarBinary, Value = DbNull.Value });

一個有趣的反作用是你還能夠從PetaPoco返回一個IDbParameters。IMapper接口從全局覆蓋了PetaPoco的默認參數映射功能。

在每一個基礎查詢禁用自動select生成的功能

PetaPoco作了一個合理的工做,猜想什麼時候應該自動插入Select子句-可是這不太完美並且有各類運行不正確的狀況。之前的版本你須要關閉EnableAutoSelect屬性,運行你的查詢而後再改回來。

如今你能夠用一個分號開頭來代表Select子句不該被插入。PetaPoco在查詢以前會移除分號。

// Leading semicolon in query will be removed...
db.Query<mytype>(";WITH R as....");

T4模板改進-自定義插件清理功能

如今能夠替換標準的T4模板中用來清理表和列名的方法。在T4模板中,在調用LoadTables方法以前設置全局CleanUp屬性爲一個委託:

CleanUp = (x) => { return MyCleanUpFunction(x); }

T4模板改進-包括架構視圖和過濾的功能

T4模板如今能夠爲數據庫中的全部架構生成類,或者僅爲一個架構。若是隻包括一個特定架構的表,在調用LoadTables方法以前設置全局的SchemaName屬性。你也能夠用一個前綴來生成類:

SchemaName = "MySchema";
ClassPrefix = "myschema_";

若是你想要一個特定的主架構或其餘架構或多架構,設置多個不一樣SchemaName的Database.ttj便可。

你還能夠用T4模板生成類視圖:

IncludeViews = true;

ReaderWriterLockSlim多線程支持改進

PetaPoco使用ReaderWriterLockSlim來保護訪問共享數據來提升多線程性能-好比在web程序中。

支持protected構造函數和屬性

PetaPoco如今能夠訪問POCO的private和protected成員-包括private構造函數和屬性訪問器。

新的Page<>.Context屬性

在一些狀況下,我一直爲MVC視圖使用PetaPoco的強類型的Model對象,但須要一些額外的數據。不想使用ViewData或新建一個新的類,所以爲Page類添加了一個Context屬性。這能夠用來傳遞一些額外的上下文數據。

好比有一個頁面須要一個partial view來顯示網站頁的縮略圖。當有頁面顯示的時候是正常的,單若是列表是空的我想顯示一個根據上下文來顯示的「blank slate」信息。這多是「你尚未收藏」或「沒有更多網站了」或「你尚未喜歡任何網站」……

爲了處理這個問題,在controller中我設置了Context屬性能夠代表若是沒有數據的時候該如何顯示空白信息。

bug修復

PetaPoco - Mapping One-to-Many and Many-to-One Relationships :http://www.toptensoftware.com/Articles/115/PetaPoco-Mapping-One-to-Many-and-Many-to-One-Relationships

如今PetaPoco支持多POCO查詢。不少人問我PetaPoco如何或是否可以映射一對多和多對一的關係。

簡單的回答是,不會。但你能夠本身作,若是你想的話。

這就是說,請肯定你是否真的須要它。若是你只是作通常的Join查詢返回POCO那是不必的。多POCO查詢的重點是在捕獲Join結果的時候避免定義新的或擴展示有的POCO對象-不是真的要提供Instance Identity。

實例標識和廢棄POCO

那麼究竟當我說"Instance Identity"的時候是什麼意思呢?我意思是,若是從兩個或更多地方的查詢返回一個特定的記錄,則全部的狀況下都返回相同的POCO實例,或該POCO實例有惟一的標識。例如,若是你正在作一個articles和authors的Join查詢,若是兩個article有相同的author,那麼將引用相同的author的對象實例。

PetaPoco的多POCO查詢老是爲每一個行建立一個新的實例。所以在上面的例子中,每一行都將建立一個新的author對象。要得到正確的Instance Identity,咱們將最終丟棄重複的-因此不要把一對多和多對一做爲提升效率的辦法-只有在更準確的對象圖對你有用的時候再使用它。

Relator Callbacks

自動映射和簡單關係

當咱們寫一個relator callback時,咱們看看簡單的自動映射多POCO查詢看起來像這樣:

var posts = db.Fetch<post, author>(@"
        SELECT * FROM posts 
        LEFT JOIN authors ON posts.author = authors.id ORDER BY posts.id
        ");

使用自動映射,第一個泛型參數是返回類型。所以這個例子將返回一個List ,post對象有一個author類型的屬性,PetaPoco將它鏈接到建立的author對象。

寫relator callback,看起來像這樣:

var posts = db.Fetch<post, author, post>(
        (p,a)=> { p.author_obj = a; return p; },
        @"SELECT * FROM posts 
        LEFT JOIN authors ON posts.author = authors.id ORDER BY posts.id
        ");

注意上面作了兩件事:

一、在泛型參數中有一個額外的<post,author,post>。最後一個參數代表了返回集合的類型。使用自定義的relator你能夠決定使用不一樣的類表明Join的行。

二、lambda表達式鏈接了post和author。

測試用例地址:https://github.com/toptensoftware/PetaPoco/blob/master/PetaPoco.Tests/MultiPocoTests.cs

多對一的關係

爲了實現多對一的關係,咱們須要作的是保持一個映射的RHS對象,並每次都重用相同的一個。

var authors = new Dictionary<long, author>();
var posts = db.Fetch<post, author, post>(
    (p, a) =>
    {
        // Get existing author object
        author aExisting;
        if (authors.TryGetValue(a.id, out aExisting))
            a = aExisting;
        else
            authors.Add(a.id, a);

        // Wire up objects
        p.author_obj = a;
        return p;
    },
    "SELECT * FROM posts LEFT JOIN authors ON posts.author = authors.id ORDER BY posts.id"
    );

實現是很簡單的:尋找之前的相同author實例,若是找到了就使用它的引用。若是沒有找到就提供一個並存儲起來供之後使用。

固然若是你須要在不少地方這樣作很快就會乏味。因此包裝一個helper:

class PostAuthorRelator
{
    // A dictionary of known authors
    Dictionary<long, author> authors = new Dictionary<long, author>();

    public post MapIt(post p, author a)
    {
        // Get existing author object, or if not found store this one
        author aExisting;
        if (authors.TryGetValue(a.id, out aExisting))
            a = aExisting;
        else
            authors.Add(a.id, a);

        // Wire up objects
        p.author_obj = a;
        return p;
    }
}

如今能夠這樣運行查詢:

var posts = db.Fetch<post, author, post>(
    new PostAuthorRelator().MapIt,
    "SELECT * FROM posts LEFT JOIN authors ON posts.author = authors.id ORDER BY posts.id"
    );

好多了,繼續……

一對多關係

在一對多關係,咱們想從RHS獲得的對象集合來填充每一個LHS對象。好比上面的例子,咱們想要一個author列表,每一個都有一個做者的文章集合。

SELECT * FROM authors 
LEFT JOIN posts ON posts.author = authors.id ORDER BY posts.id

使用這個查詢咱們會獲得LHS結果集中的重複的author信息,文章信息在右面。左邊的author須要去重獲得單一的POCO,文章須要爲每一個author收集成一個list。

返回的集合事實上會比數據庫返回的行有更少的項,因此relator callback須要可以hold back當前的author直到檢測到一個新的author。

爲了支持這點,PetaPoco容許一個relator callback來返回null表示還沒爲當前記錄準備好。爲了清空最後的記錄PetaPoco將在結果集末尾最後調用一次relator,爲全部的參數傳遞null(但它只能作這個,若是relator在結果集中至少返回一次-relator不用檢查null參數更簡單了)

看一下一對多的relator:

class AuthorPostRelator
{
    public author current;
    public author MapIt(author a, post p)
    {
        // Terminating call.  Since we can return null from this function
        // we need to be ready for PetaPoco to callback later with null
        // parameters
        if (a == null)
            return current;

        // Is this the same author as the current one we're processing
        if (current != null && current.id == a.id)
        {
            // Yes, just add this post to the current author's collection of posts
            current.posts.Add(p);

            // Return null to indicate we're not done with this author yet
            return null;
        }

        // This is a different author to the current one, or this is the 
        // first time through and we don't have an author yet

        // Save the current author
        var prev = current;

        // Setup the new current author
        current = a;
        current.posts = new List<post>();
        current.posts.Add(p);

        // Return the now populated previous author (or null if first time through)
        return prev;
    }
}

上面的註釋很清楚的代表發生了什麼-咱們只是簡單的保存author直到咱們檢測到一個新的而後添加文章列表到當前的author對象,這樣來用:

var authors = db.Fetch<author, post, author>(
    new AuthorPostRelator().MapIt,
    "SELECT * FROM authors LEFT JOIN posts ON posts.author = authors.id ORDER BY posts.id"
    );

雙向映射,映射兩個以上的對象

在上面的例子中,我要麼把author映射到post要麼添加post到author列表。relator沒有理由作不到同時使用這兩種方式建立的引用。我沒有包括這個例子只是爲了證實這是可行的可是你懂得。

最後,上面的例子只是展現瞭如何聯繫兩個對象。若是你鏈接更多的表你須要作更多複雜的工做,單只是上面例子的擴展。

PetaPoco-Partial Record Updates

http://www.toptensoftware.com/Articles/116/PetaPoco-Partial-Record-Updates

默認狀況下,PetaPoco更新記錄的時候會更新全部的被映射到POCO屬性的列。根據不一樣的使用狀況,一般是能夠的但也許無心中覆蓋了已經被其餘事務更新過的字段。

例如:

var u = user.SingleOrDefault("WHERE name=@0", username);
u.last_login = DateTime.UtcNow;
u.Update();

問題是全部的字段都被更新了-用戶名、郵件地址、密碼,全部的都重寫到數據庫。若是隻是更新last_login字段會更好一些。咱們能夠這樣寫:

u.Update(new string[] { "last_login" });

或相似的:

db.Update<user>(u, new string[] { "last_login" });

全部的Update方法如今都有一個新的重載,接受一個新參數,定義爲IEnumerable 指定應該被更新的列的名稱(不是屬性).

這是有用的除非跟蹤哪些列須要更新很是痛苦。T4模板生成的POCO類如今能夠自動跟蹤修改的屬性。爲了啓用它,Database.tt中有一個設置選項:

TrackModifiedColumns = true;

當設置爲false的時候,POCO屬性以舊方式實現:

[Column] string title { get; set; }

當爲true時,它生成跟蹤修改列的訪問器方法;

[Column] 
public string title 
{ 
    get
    {
        return _title;
    }
    set
    {
        _title = value;
        MarkColumnModified("title");
    }
}
string _title;

基本的Record類有一些新方法:

private Dictionary<string,bool> ModifiedColumns;
private void OnLoaded()
{
    ModifiedColumns = new Dictionary<string,bool>();
}
protected void MarkColumnModified(string column_name)
{
    if (ModifiedColumns!=null)
        ModifiedColumns[column_name]=true;
}
public int Update() 
{ 
    if (ModifiedColumns==null)
        return repo.Update(this); 

    int retv = repo.Update(this, ModifiedColumns.Keys);
    ModifiedColumns.Clear();
    return retv;
}
public void Save() 
{ 
    if (repo.IsNew(this))
        repo.Insert(this);
    else
        Update();
}

解釋一下:

一、OnLoaded是一個新方法,PetaPoco在從數據庫填充任何POCO實現後都將當即調用它。

二、MarkColumnsModified-簡單的記錄OnLoaded被調用後有值被更改的列名。

三、執行Update時Update和Save已經更新爲傳遞一個修改列的list給PetaPoco。

有一點須要注意的,set訪問器,它們標誌了列被修改 實際上值並無改變。這是故意的,有兩個緣由:

一、它確保值不管如何確實被髮送到數據庫,幫助保持數據一致性。

二、這意味着查詢數據庫不依賴於用戶輸入的數據。例如:若是兩個用戶使用一樣的表單來改變他們的資料,一個改變了他們的郵件地址,另外一個改變了他們的顯示名稱,均會致使數據庫相同的update查詢-數據庫只能優化一次。

Long Time No Post and PetaPoco v5

http://www.toptensoftware.com/Articles/137/Long-Time-No-Post-and-PetaPoco-v5

本文主要是V5版本的一些更新……實在沒有力氣翻譯了。8-(

相關文章
相關標籤/搜索