【问题标题】:ServiceStack's Ormlite Delete not workingServiceStack 的 Ormlite Delete 不起作用
【发布时间】:2015-01-18 06:54:23
【问题描述】:

我已经创建了一个通用存储库来在 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

当我执行这个完美感知的语句时,服务器告诉我没有行

免责声明:有些名字是我的母语,我翻译了它们,所以可能会有一点语法错误,如果是这样,让我记下,我会编辑。

更新

匹配的行实际上存在于数据库中

SELECT * FROM FT_TEST_DEVELOPMENT WHERE ID= 4 ID 描述 时间戳 日期 价格 数量 4 第二个空 2015-06-01 15 空

我的意思是实际上 OrmLite 生成的代码似乎有问题。

是的,ID 列是表的键。

第二次更新 我想我找到了原因:

实际上在WHERE 子句中,NULL 字段的分配方式

@TIMESTAMP=NULL

但实际上SQL服务器不会匹配这个语句,因为它期望接收

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

【问题讨论】:

  • 您将ID 定义为表中的主键还是只是IDENTITYIDENTITY 不将字段标记为主键
  • 卡利斯佩拉!我也尝试了 [PrimaryKey] 属性,但没有任何改变,无论如何我会编辑问题,THX
  • 您需要将 [PrimaryKey] 放在那里确保 ID 是桌子上的主键。另外,我怀疑db.Delete&lt;T&gt;() 是一个错字,你的意思是db.Delete&lt;T&gt;(entity)。所有这一切都应该更改语句的WHERE 子句以仅检查 ID 字段。还要确保行符合条件

标签: c# servicestack ormlite-servicestack


【解决方案1】:

db.Delete() API 的工作方式has been updated 使NULL 字段从参数化查询中移出并附加到 SQL 过滤器,因此现在应该从 v4.0.37+ 开始工作现在available on MyGet

您还可以通过 PrimaryKey 删除 OrmLite 中的行:

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

对于泛型方法,你可以使用T.GetId()扩展方法来获取Id字段的值,即:

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

或使用DELETE WHERE 条件中的每个 null 属性删除,您可以使用:

Db.DeleteNonDefaults(entity);

【讨论】:

  • 好的,谢谢,但还有一个问题。为什么即使方言是 SqlServerDialect.Provider 生成的 WHERE 子句也不会匹配任何行?
  • @Pizzaboy 因为它使用参数化查询来执行过滤器并将空字段与参数化值(即使它是 DbNull)进行比较会产生错误条件。您可以使用Db.DeleteNonDefaults(),因此过滤器中不使用空字段,否则我的首选是使用带有Db.DeleteById() 的主键删除。
【解决方案2】:

如果您在 SSMS 中执行相同的语句并且没有任何内容被删除,那是因为没有行符合条件。

OrmLite 期望实体的主键命名为Id(区分大小写)。您的属性名为 ID 并且未指定 [PrimaryKey] 属性。在这种情况下,OrmLite 必须使用 WHERE 子句中的所有可用字段来查找要删除的行。

AutoIncrement 并不意味着该字段是一个键,只是它的值是由服务器自动生成的并且来自一个标识列。这同样适用于 SQL Server - 标识列不是主键,您需要单独定义主键。

您需要将ID 重命名为Id 或添加[PrimaryKey] 属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多