NPoco:为什么我的Delete <model>()调用,抛出NullReferenceException?</model>

时间:2014-08-01 14:23:18

标签: c# petapoco npoco

我尝试使用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]

1 个答案:

答案 0 :(得分:2)

关注GitHub repository中的来源,看起来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);

Delete<PurchaseItem>("where id = @0", id);有效的原因是,它遵循不同的代码路径,其中用于解析PocoData的类型来自typeof(T),其中T为{{1} }}