LiteDB:字段'_id'上的BSON数据类型无效'Null' [英] LiteDB: Invalid BSON data type 'Null' on field '_id'

查看:98
本文介绍了LiteDB:字段'_id'上的BSON数据类型无效'Null'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 LiteDB ,真是太神奇了.它适用于加载和存储数据,但是不适用于创建数据库后的后续加载.

Using LiteDB, and it is amazing. It works well for loading and storing data, however, not on subsequent loads after the database has been created.

在初始加载时,一切都很完美.它创建数据库并完美地存储新记录,并且由于该集合中还没有任何内容,因此查询返回空值.

On initial load, everything is perfect. It creates the database and stores the new record flawlessly, and query returns empty since nothing exists in that collection yet.

在随后的加载中,查询数据(工作并获取结果)后, .Update()中存在问题,这是导致此问题的原因.根据他们的文档,当未指定"Id"时,应创建一个.从集合返回对象时,该对象不包含此"_Id"字段,因此无法更新数据库中的记录.

On subsequent load, after querying the data (works and gets the result), there is a problem in the .Update() which is causing this issue. According to their documentation, when an 'Id' is not specified it is supposed to create one. When the object is returned from the collection, it does not contain this '_Id' field, and thus fails to update the record in the database.

public class AuctionCache
{
    public double lastModified { get; set; }
    public string server { get; set; }
    public AuctionCache() { }
}

private static bool IsCached(AuctionCache auction)
{
    string filename = string.Format("{0}-{1}.json", auction.server, auction.lastModified);
    bool cached = false;
    try
    {
        using (LiteDatabase db = new LiteDatabase("cache.db"))
        {
            // Get customer collection
            var auctions = db.GetCollection<AuctionCache>("auctions");

            // Use Linq to query documents
            try
            {
                var results = auctions.Find(x => x.server == auction.server).DefaultIfEmpty(null).Single();
                if (results == null)
                {
                    // Insert new cached server
                    auctions.Insert(auction);
                    auctions.EnsureIndex(x => x.server);
                }
                else
                {
                    if (results.lastModified < auction.lastModified)
                    {
                        // Update existing cached server data
                        results.lastModified = auction.lastModified;
                        auctions.Update(results);
                        auctions.EnsureIndex(x => x.server);
                    }
                    else
                    {
                        cached = File.Exists(filename);
                    }
                }
            }
            catch (LiteException le1) {
                Log.Output(le1.Message);
                // Get stack trace for the exception with source file information
                var st = new StackTrace(le1, true);
                // Get the top stack frame
                var frame = st.GetFrame(0);
                // Get the line number from the stack frame
                var line = frame.GetFileLineNumber();
                var module = frame.GetMethod();
                var file = frame.GetFileName();
            }
            catch (Exception e)
            {
                Log.Output(e.Message);
                // Get stack trace for the exception with source file information
                var st = new StackTrace(e, true);
                // Get the top stack frame
                var frame = st.GetFrame(0);
                // Get the line number from the stack frame
                var line = frame.GetFileLineNumber();
            }
        }
    } catch (Exception ee) {
        Log.Output(ee.Message);
        // Get stack trace for the exception with source file information
        var st = new StackTrace(ee, true);
        // Get the top stack frame
        var frame = st.GetFrame(0);
        // Get the line number from the stack frame
        var line = frame.GetFileLineNumber();
    }
    return cached;
}

如果您希望快速使用上面的代码,可以将以下内容用于演示目的(初始加载):

If you wish to use the above code quickly, you can use the following for demonstration purposes (initial load) :

   AuctionCache ac = new AuctionCache();
   ac.lastModified = (double)12345679;
   ac.server = "Foo";

   // should return true on subsequent loads.
   Console.WriteLine( IsCached( ac ) );

请确保在进行测试以在首次创建后停止该程序,然后使用以下代码全新"启动该程序以进行干净的加载/更新数据库测试:

Make sure when testing to stop the program after initial creation, and then start the program 'fresh' for a clean test of loading / updating the database using the following code :

   AuctionCache ac = new AuctionCache();
   ac.lastModified = (double)22345679;
   ac.server = "Foo";

   // should return true on subsequent loads.
   Console.WriteLine( IsCached( ac ) );

这应该确保它会尝试更新记录并在IDE中标记问题,因为 lastModified 比存储在 cache.db 中的更新版本要新.我的 IsCached 方法中的 .Update 方法.

This should ensure that it will try to update the record and flag the problem in your IDE as lastModified is newer than the one stored in cache.db which will trigger the .Update method inside my IsCached method.

推荐答案

当您有一个没有标识的对象时,LiteDB会将您的对象转换为BsonDocument并在插入时创建一个新的"_id".如果您查询数据库(使用外壳程序),则可以在其中看到带有_id(ObjectId)的文档.

When you have a object without an identification, LiteDB convert your object to BsonDocument and create a new "_id" on insert. If you query your database (using shell) you can see your document there with an _id (ObjectId).

但是,要更新文档,您必须使用在插入时生成的_id(请参见此处:

But, to update your document, you must use this _id generated on insert (see here: https://github.com/mbdavid/LiteDB/blob/v2.0.0-rc/LiteDB/Core/Collections/Update.cs#L25). Documents without id is useful only when you store this _id in another database (sql) or for insert only.

在您的示例中,如果 server 是您的文档ID,请使用 [BsonId] 属性来解决或创建一个公共Guid ID {get;放;}

In you example, if server is you document id, use [BsonId] attribute to solve or create an public Guid Id { get; set; }

这篇关于LiteDB:字段'_id'上的BSON数据类型无效'Null'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆