2015-01-15 45 views
0

我已經構建了一個通用的存儲庫,以在MVC項目中進行CRUD操作。ServiceStack的Ormlite刪除不起作用

當我嘗試從SQLServer上具有標識的表中刪除一行時,由Ormlite Delete方法生成的代碼和使用分析器檢查不會影響任何行。

這是刪除(非常簡單)渣滓操作:

public void Destroy<T>(T entity) 
    { 
     using (var db = dbFactory.Open()) 
     { 
      db.Delete<T>(entity); 
     } 
    } 

在我的測試的類型T由以下類表示:

[Alias("FT_TEST_DEVELOPMENT")] 
public class TestTable 
{ 
    [AutoIncrement] 
    [PrimaryKey] 
    public int ID { get; set; } 
    public string DESCR { get; set; } 
    public DateTime? TIMESTAMP { get; set; } 
    public DateTime DATE { get; set; } 
    public decimal PRICE { get; set; } 
    public int? QTY { get; set; } 
} 

且所檢查的代碼對應於如下:

exec sp_executesql N'DELETE FROM "FT_TEST_DEVELOPMENT" WHERE "ID"[email protected] AND "DESCR"[email protected] AND "TIMESTAMP"[email protected] AND "DATE"[email protected] AND "PRICE"[email protected] AND "QTY"[email protected] ', 
       N'@ID int,@DESCR nvarchar(6),@TIMESTAMP datetime,@DATE datetime,@PRICE decimal(2,0),@QTY int', 
       @ID=4,@DESCR=N'SECOND',@TIMESTAMP=NULL,@DATE='2015-06-01 00:00:00',@PRICE=15,@QTY=NULL 

當我執行這個完美的感覺d語句服務器告訴我,沒有行

免責聲明:因爲有些名稱在我的母語中,我翻譯過它們,所以可能會有小的語法錯誤,如果是這樣,請讓我注意一下,然後我會編輯。

UPDATE

匹配行實際上在數據庫

SELECT * FROM FT_TEST_DEVELOPMENT WHERE ID = 4 ID DESCR TIMESTAMP DATE價格數量 4 SECOND NULL 2015年6月1日15 NULL

EXISTS

我的意思是實際上OrmLite生成的代碼似乎被竊聽。

是的,ID列是表的關鍵。

第二次更新 我想我已經找到了癥結:

其實WHERE子句中的NULL字段的方式

@TIMESTAMP=NULL 

分配,但實際上SQL服務器將不匹配此聲明,因爲它期望收到

WHERE [...] AND "TIMESTAMP" IS NULL [...] 
+1

您是否將'ID'定義爲表中的主鍵,還是僅僅是一個'IDENTITY'? 'IDENTITY'不會將字段標記爲主鍵 – 2015-01-15 15:57:32

+0

Kalispera!我也嘗試過使用** [PrimaryKey] **屬性,但沒有任何改變,無論如何,我將編輯問題,THX – Pizzaboy 2015-01-15 16:00:38

+1

您需要將[PrimaryKey]放在*和*確保ID是主鍵表。此外,我懷疑'db.Delete ()'是一個錯字,你的意思是'db.Delete (實體)'。所有這些都應該改變語句的'WHERE'子句來僅檢查ID字段。還要確保有*行*符合條件 – 2015-01-15 16:03:43

回答

2

方式db.Delete() API的工作has been updated使NULL場被移出參數化查詢和附加到SQL過濾器所以這應該從現在v4.0.37 +這就是現在available on MyGet工作。

您也可以刪除行中OrmLite通過的PrimaryKey有:

Db.DeleteById<TestTable>(entity.Id); 

對於通用的方法,你可以使用T.GetId()擴展方法來獲得標識字段的值,即:

Db.DeleteById<TestTable>(entity.GetId()); 

或刪除使用null屬性中的DELETE WHERE標準,您可以使用:

Db.DeleteNonDefaults(entity); 
+0

好吧謝謝,但只是一個問題。爲什麼即使方言是** SqlServerDialect.Provider **生成的** WHERE **子句將不會匹配任何行? – Pizzaboy 2015-01-16 07:36:21

+1

@Pizzaboy因爲它使用參數化查詢來執行過濾器並將空字段與參數化值進行比較(即使它是DbNull)也會產生錯誤的條件。你可以使用'Db.DeleteNonDefaults()',所以在過濾器中不使用空字段,否則我的首選是使用帶有'Db.DeleteById()'的主鍵來刪除。 – mythz 2015-01-16 08:05:11

1

如果您執行在SSMS中相同的語句,沒有被刪除,這是因爲沒有行符合條件。

OrmLite預計實體的主鍵名爲Id(區分大小寫)。您的財產被命名爲ID,並且未指定[PrimaryKey]屬性。在這種情況下,OrmLite必須使用WHERE子句中的所有可用字段來查找要刪除的行。

AutoIncrement並不意味着該字段是關鍵字,只是它的值由服務器自動生成並來自標識列。這同樣適用於SQL Server - 標識列不是主鍵,您需要單獨定義主鍵。

您需要將ID重命名爲Id或將[PrimaryKey]屬性添加到它。