【问题标题】:NullReferenceException Query SQLite database with Where on a concatenated string propertyNullReferenceException 在连接字符串属性上使用 Where 查询 SQLite 数据库
【发布时间】:2017-09-22 10:20:17
【问题描述】:

我正在尝试使用以下代码选择一条记录:

Location item = connection
  .Table<Location>()
  .Where(l => l.Label.Equals(label))
  .FirstOrDefault();

这会导致:

System.NullReferenceException:对象引用未设置为对象的实例。

当我在不同的属性(邮政编码)上尝试相同的方法时,如果没有找到记录,它也可以正常工作。:

Location item = connection
  .Table<Location>()
  .Where(l => l.Postcode.Equals(label))
  .FirstOrDefault();

这是位置类:

// These are the Locations where the Stock Take Sessions are done
public class Location : DomainModels, IComparable<Location>
{
    [JsonProperty("id"), PrimaryKey]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Street { get; set; }
    public int Number { get; set; }
    public string Postcode { get; set; }
    public string City { get; set; }
    public bool Completed { get; set; }

    [Ignore] // Removing this does not have an impact on the NullReferenceException
    public string Label => $"{Name ?? ""} - ({Postcode ?? ""})";

    public int CompareTo(Location other)
    {
        return Name.CompareTo(other.Name);
    }

    // Navigation property
    // One to many relationship with StockItems
    [OneToMany(CascadeOperations = CascadeOperation.All), Ignore]
    public List<StockItem> StockItems { get; set; }

    // Specify the foreign key to StockTakeSession
    [ForeignKey(typeof(StockTakeSession))]
    public int StockTakeSessionId { get; set; }

    // One to one relationship with StockTakeSession
    [OneToOne]
    public StockTakeSession StockTakeSession { get; set; }

}

我做错了什么?

感谢您的任何建议!

【问题讨论】:

  • connection.Table&lt;Location&gt; 中的Location 之一具有Label = null。这就是为什么你有这个问题。您需要确保 connection.Table&lt;Location&gt; 中的所有项目都设置了 Label 属性。
  • @ChetanRanpariya:我检查了数据库,没有一条记录缺少姓名或邮政编码。

标签: c# android sqlite-net-extensions


【解决方案1】:

您在Label在数据存储中 的 where 过滤器您在班级 Location 上的标记已用 IgnoreAttribute 修饰了 Label 属性。这意味着Label 属性直到实体被具体化到内存之后才会设置,并且您无法在数据存储中对其进行任何操作。

.Where(l => l.Label.Equals(label))

修复

有一些选择。

  • 您可以将其设置为计算并使用相同的逻辑在存储中创建一个计算列。这涉及直接在 RDBMS 管理器中手动更改表架构或编辑迁移脚本。该属性被标记为[DatabaseGenerated(DatabaseGeneratedOption.Computed)]如果使用属性,您上面的代码就是)。
  • 您可以更改 Where 以过滤在商店中找到的构成 Label 的属性。即:.Where(l =&gt; l.Postcode.Equals(Postcode) &amp;&amp; l.Name.Equals(Name))
  • 您可以将特定过滤器之前的所有内容具体化到内存中,然后应用过滤器。 如果到那时为止的所有内容都会导致大量记录,则不建议这样做。例如,如果表很大,则使用下面的代码,您将检索单个记录的所有内容。

    Location item = connection
      .Table<Location>()
      .AsEnumerable()
      .Where(l => l.Label.Equals(label))
      .FirstOrDefault();
    

编辑

[Ignore] //去掉这个对NullReferenceException没有影响

不,除非您将具有相同名称的列添加到现有架构中使用所有数据填充它,否则不应该这样做。 (或在您的架构中创建一个具有相同名称的计算列

【讨论】:

  • 谢谢@Igor。你能告诉我你为第一个和第三个项目符号建议的代码吗?我对此很陌生,以完全理解您的意思,并且代码示例可能会有所帮助。谢谢!
  • @Robert - 完成。我没有添加关于如何在您的数据存储中创建计算列的代码,但您可以通过搜索在线找到。
  • 我选择了第一个选项,但这似乎与实体框架相关。我对吗?我将 SQLite-Net 与 SQLite.Net.Attributes 和 SQLiteNetExtensions.Attributes 一起使用。两者都不支持 [DatabaseGenerated] 属性。
  • @Robert - 我对sql-lite 几乎一无所知,但如果 rdbms 支持计算列,它应该可以工作。该属性与提供者无关:DatabaseGeneratedAttribute
  • 没问题,感谢您的宝贵时间。为了解决这个问题,我将在记录插入数据库时​​生成标签。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多