2015-01-15 71 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]属性添加到它。