2

当我的页面加载时,我从数据库中加载一个列表SQLite,有时当它加载时我收到NullReferenceException错误消息Object reference not set to an instance of an object.

它在 SQLite 类文件中打破了这段代码

public TableMapping GetMapping (Type type)
{
    if (_mappings == null) {
        _mappings = new Dictionary<string, TableMapping> ();
    }
    TableMapping map;
    if (!_mappings.TryGetValue (type.FullName, out map)) {
        map = new TableMapping (type);
        _mappings [type.FullName] = map; //null here
    }
    return map;
}

这就是我在页面加载时所做的

public MainPage()
{
    this.InitializeComponent();
    Loaded += MainPage_Loaded;
}

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    createDatabase();
    getBowlers();
}

private async void createDatabase()
{
    SQLiteAsyncConnection conn = new SQLiteAsyncConnection(BOWLERS_DATABASE);
    await conn.CreateTableAsync<Bowler>();
    conn = new SQLiteAsyncConnection(GAMES_DATABASE);
    await conn.CreateTableAsync<Games>();
}

private async void getBowlers()
{
    SQLiteAsyncConnection conn = new SQLiteAsyncConnection(BOWLERS_DATABASE);

    var query = conn.Table<Bowler>();
    itemListView.DataContext = await query.ToListAsync();
}

我是页面生命周期的新手,但似乎我正试图从数据库拉到早期可能?

编辑

堆栈跟踪

System.NullReferenceException was unhandled by user code
HResult=-2147467261
Message=Object reference not set to an instance of an object.
Source=mscorlib
StackTrace:
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.set_Item(TKey key, TValue value)
   at SQLite.SQLiteConnection.GetMapping(Type type) in c:\Users\Jeff\Dropbox\Tournament Director Windows\Tournament Director Windows\SQLite.cs:line 231
   at SQLite.TableQuery`1..ctor(SQLiteConnection conn) in c:\Users\Jeff\Dropbox\Tournament Director Windows\Tournament Director Windows\SQLite.cs:line 2129
   at SQLite.SQLiteConnection.Table[T]() in c:\Users\Jeff\Dropbox\Tournament Director Windows\Tournament Director Windows\SQLite.cs:line 616
   at SQLite.SQLiteAsyncConnection.Table[T]() in c:\Users\Jeff\Dropbox\Tournament Director Windows\Tournament Director Windows\SQLiteAsync.cs:line 260
   at Tournament_Director_Windows.MainPage.<getBowlers>d__c.MoveNext() in c:\Users\Jeff\Dropbox\Tournament Director Windows\Tournament Director Windows\MainPage.xaml.cs:line 116
InnerException: 
4

3 回答 3

4

根据异常和提供的堆栈跟踪,我认为您的问题是此处描述的问题。

笔记:

  1. 异常是从 Dictionary 代码中引发的,而不是从您的(用户)代码中引发的
  2. 异常是 NullReferenceException,而不是 ArgumentNullException,因此不仅仅是参数为 null

字典不是线程安全的。这意味着如果它被多个线程访问,那么对它的访问应该是同步的。

更新 1

SQLite 异步处理中似乎存在错误

于 2013-07-09T05:16:53.910 回答
1

原始代码的问题在于 GetMapping 方法不是线程安全的。在下面添加一个锁,强制它是线程安全的并解决了这个问题。

根据答案和评论,这里是代码,将 SQLite.cs 文件中的 GetMapping 方法更改为此

private Object thisLock = new Object(); // add lock obj
public TableMapping GetMapping(Type type, CreateFlags createFlags = CreateFlags.None)
{
    // include original code in the lock block
    lock (thisLock)
    {
        if (_mappings == null)
        {
            _mappings = new Dictionary<string, TableMapping>();
        }
        TableMapping map;
        if (!_mappings.TryGetValue(type.FullName, out map))
        {
            map = new TableMapping(type, createFlags);
            _mappings[type.FullName] = map;
        }
        return map;
    }
}
于 2015-05-12T00:51:00.703 回答
0

试试这个:

if (!_mappings.ContainsKey(type.FullName))
{
    _mappings.Add(map);
}

_mappings [type.FullName] = map;
于 2013-07-09T01:01:27.937 回答