我已经组建了一个通用存储库来在MVC项目中进行CRUD操作。
当我尝试从SQLServer上具有标识的表中删除行时,Ormlite Delete
方法生成并使用分析器检查的代码不会影响任何行。
这是删除的Crud操作(非常简单):
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"=@ID AND "DESCR"=@DESCR AND "TIMESTAMP"=@TIMESTAMP AND "DATE"=@DATE AND "PRICE"=@PRICE AND "QTY"=@QTY ',
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
当我执行这个完美感知的语句时,服务器告诉我没有行
免责声明:有些名字在我的母语中,我翻译了它们,因此可能没有语法错误,如果是这样的话,请注意,我会编辑。
更新
匹配的行实际上是数据库中的EXISTS
SELECT * FROM FT_TEST_DEVELOPMENT WHERE ID = 4 ID DESCR TIMESTAMP日期价格数量 4 SECOND NULL 2015-06-01 15 NULL
我的意思是实际上OrmLite生成的代码似乎被窃听了。
是的,ID列是表的密钥。
第二次更新 我想我找到了原因:
实际上在WHERE
子句中,NULL字段以
@TIMESTAMP=NULL
但实际上SQL服务器与此语句不匹配,因为它希望接收
WHERE [...] AND "TIMESTAMP" IS NULL [...]
答案 0 :(得分:2)
db.Delete()
API的工作方式has been updated,以便NULL
字段移出参数化查询并附加到SQL过滤器,因此现在可以使用 v4.0.37 + 现在available on MyGet。
您还可以使用以下方法删除OrmLite中的行:
Db.DeleteById<TestTable>(entity.Id);
对于通用方法,您可以使用T.GetId()
扩展方法获取Id字段的值,即:
Db.DeleteById<TestTable>(entity.GetId());
或者要使用null
WHERE条件中的每个非 DELETE
属性进行删除,您可以使用:
Db.DeleteNonDefaults(entity);
答案 1 :(得分:1)
如果在SSMS中执行相同的语句并且没有任何内容被删除,那是因为没有符合条件的行。
OrmLite期望实体的主键名为Id
(区分大小写)。您的属性名为ID
,未指定[PrimaryKey]
属性。在这种情况下,OrmLite必须使用WHERE
子句中的所有可用字段来查找要删除的行。
AutoIncrement
并不意味着该字段是一个键,只是它的值由服务器自动生成并来自标识列。这同样适用于SQL Server - 标识列不是主键,您需要单独定义主键。
您需要将ID
重命名为Id
或向其添加[PrimaryKey]
属性。