NPoco:为什么我的Delete<Model>()调用会抛出NullReferenceException?

4
我正在尝试使用NPoco的Delete()方法从数据库中删除一行数据。然而,它却抛出了一个NullReferenceException异常。
我已经找到了一个解决方法,但我想知道为什么内置的按ID删除函数对我似乎无法起作用。这在多个表格上发生。我的所有表格都有一个名为ID的标准整数主键,并已使用[PrimaryKey("ID")]修饰符在模型中标记。
对象引用未设置为对象的实例。
Delete<PurchaseItem>(id); // throws null reference exception.
Delete<PurchaseItem>("where id = @0", id);  // works.

传递的ID是有效的,该项在数据库中存在。代码没有执行任何SQL。

堆栈跟踪:

[NullReferenceException: Object reference not set to an instance of an object.]
   NPoco.PocoDataFactory.ForObject(Object o, String primaryKeyName) in d:\Adam\projects\NPoco\src\NPoco\PocoDataFactory.cs:41
   NPoco.Database.Delete(String tableName, String primaryKeyName, Object poco, Object primaryKeyValue) in d:\Adam\projects\NPoco\src\NPoco\Database.cs:1587
   NPoco.Database.Delete(Object pocoOrPrimaryKey) in d:\Adam\projects\NPoco\src\NPoco\Database.cs:1598
   Harmsworth.DAL.HarmsworthDB.DeletePurchaseItemFromBasketByID(Int32 id) in c:\inetpub\wwwroot\harmsworth\Website\classes\HarmsworthDAL.cs:224
   Harmsworth.ViewBasketPage.RemoveItem(Int32 id) in c:\inetpub\wwwroot\harmsworth\Website\view-basket.aspx.cs:187
   Harmsworth.ViewBasketPage.PurchaseItemsRepeater_ItemCommand(Object sender, RepeaterCommandEventArgs e) in c:\inetpub\wwwroot\harmsworth\Website\view-basket.aspx.cs:75
   System.Web.UI.WebControls.Repeater.OnItemCommand(RepeaterCommandEventArgs e) +111
   [more redundant trace info]

异常堆栈跟踪是什么? - Trevor Pilley
@TrevorPilley 哎呀 - 已添加 :) - NickG
1
展示你的 PurchaseItem 类声明可能会有所帮助。 - chue x
id是什么,是一个int,还是Guid - Trevor Pilley
PK 是一个整数(在我的问题中确实如此 :))。 - NickG
1
这个问题已经在最新版本中得到修复。> 2.5.75 - Schotime
1个回答

3

根据GitHub存储库中的源代码,似乎NPoco存在一个错误:

您尚未指定id的类型,但我将假设它是int类型,并且您有以下代码:

var id = 12345;
Delete<PurchaseItem>(id);

这里调用了NPoco的Delete<T>(object pocoOrPrimaryKey),其代码如下:

public int Delete<T>(object pocoOrPrimaryKey)
{
    if (pocoOrPrimaryKey.GetType() == typeof(T))
        return Delete(pocoOrPrimaryKey);
    var pd = PocoDataFactory.ForType(typeof(T));
    return Delete(pd.TableInfo.TableName, pd.TableInfo.PrimaryKey, null, pocoOrPrimaryKey); // This is the method your code calls
}

这将调用NPoco Delete(string tableName, string primaryKeyName, object poco, object primaryKeyValue),其代码如下:

public virtual int Delete(string tableName, string primaryKeyName, object poco, object primaryKeyValue)
{
    if (!OnDeleting(new DeleteContext(poco, tableName, primaryKeyName, primaryKeyValue))) return 0;
    var pd = PocoDataFactory.ForObject(poco, primaryKeyName);
    ...
}

根据您的堆栈跟踪,PocoDataFactory.ForObject 方法会抛出异常,因此我只包含了前两行。ForObject(object o, string primaryKeyName) 的代码如下:

public PocoData ForObject(object o, string primaryKeyName)
{
    var t = o.GetType(); // This is where the exception comes from
    ...
}

以下是正在发生的事情(假设 id 为 12345,表映射为 PurchaseItem,主键映射为 Id):
Delete<PurchaseItem>(pocoOrPrimaryKey : 12345);
Delete(tableName: "PurchaseItem", primaryKeyName: "Id", poco: null, primaryKeyValue: 12345);
PocoDataFactory.ForObject(o: null, primaryKeyName: Id);
< p > < code > Delete<PurchaseItem>("where id = @0", id); 之所以能够工作,是因为它遵循了不同的代码路径,其中用于解析 < code > PocoData 的类型来自 < code > typeof(T) ,其中 < code > T 是 < code > PurchaseItem 。 < /p >

我已经给两个表都添加了主键装饰器。所以它应该知道。 - NickG
一定是在使用旧版本的库,因为最新版不会出现这种情况。 - Schotime
2
更新:抱歉...这是一个错误。它只在2.4.72中引入,所以我今天会发布一个版本。谢谢。@TrevorPilley - Schotime

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接