繁体   English   中英

从 LiteDB 检索记录时出现 InvalidCastException

[英]InvalidCastException when retrieving a record from LiteDB

我通过 LiteDb.Shell.exe 插入了一条记录,当我尝试在我的代码中检索该记录时,它会抛出一个InvalidCastException 如果我尝试通过 shell 查找记录,我会得到一个Unable to cast object of type 'System.Int32' to type 'System.String'.

这是我的模型

public class Query
{
    public int Id { get; set; }
    public string FilePath { get; set; }
    public string Hash { get; set; }
    public string[] Arguments { get; set; }
    public int[] PrintoutIds { get; set; }
}

这是我用来插入记录的shell命令

db.queries.insert {FilePath: "C:/Temp/Reporting Test.sql", Hash: "8074458BDE071C6B05A6EE1C718EC29CC92C89A2967D6E314EADEB0BA60F270E", Arguments: ["Tenant_ID"], PrintoutIds: [1]}

这是我用来尝试取回记录的 shell 命令

> db.queries.find
[1]: {"_id":{"$oid":"5a0ef5219996a32e14886d6b"},"FilePath":"C:/Temp/Reporting Test.sql","Hash":"8074458BDE071C6B05A6EE1C718EC29CC92C89A2967D6E314EADEB0BA60F270E","Arguments":["Tenant_ID"],"PrintoutIds":[1]}
> db.queries.find PrintoutIds contains 1
Unable to cast object of type 'System.Int32' to type 'System.String'.
> db.queries.find PrintoutIds contains "1"
> db.queries.find $.PrintoutIds[*] contains 1
Unable to cast object of type 'System.Int32' to type 'System.String'.
> db.queries.find $.PrintoutIds[*] contains "1"

这是我用来检索记录的代码

public IEnumerable<dynamic> DoStuffWithAQuery(int id)
{
    using (var reportDatabase = new LiteDatabase("C:/Stuff/Database/Reporting/Reports.db"))
    {
        var queryCollection = reportDatabase.GetCollection<Query>("queries");                                   
        queryCollection.EnsureIndex(x => x.PrintoutIds, "$.PrintoutIds[*]");
        Query query;
        try
        {
            // The next line throws an InvalidCastException.
            query = queryCollection.Find(x => x.PrintoutIds.Contains(id)).Single();
        }
        catch (InvalidOperationException)
        {
            throw new WebFaultException<string>("Only one query can be mapped to a printout",
                HttpStatusCode.BadRequest);
        }

        return DoSomeStuff(query);
    }
}

这是我得到的完整堆栈跟踪

The server encountered an error processing the request. The exception message is 'Specified cast is not valid.'. See server logs for more details. The exception stack trace is:

at
 lambda_method(Closure , Object , Object ) at
 LiteDB.BsonMapper.DeserializeObject(Type type, Object obj, BsonDocument value) at
 LiteDB.BsonMapper.Deserialize(Type type, BsonValue value) at
 LiteDB.BsonMapper.ToObject(Type type, BsonDocument doc) at
 LiteDB.BsonMapper.ToObject[T](BsonDocument doc) at
 LiteDB.LiteCollection`1.<Find>d__17.MoveNext() at
 System.Linq.Enumerable.Single[TSource](IEnumerable`1 source) at
 ReportService.DoStuffWithAQuery(String tenantName, Int32 id, Object parameters) in C:\C# Workspace\MyProject\ReportService.cs:line 35 at
 SyncInvokeDoStuffWithAQuery(Object , Object[] , Object[] ) at
 System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) at
 System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at
 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at
 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage41(MessageRpc& rpc) at
 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage4(MessageRpc& rpc) at
 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) at
 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage3(MessageRpc& rpc) at
 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage2(MessageRpc& rpc) at
 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at
 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage1(MessageRpc& rpc) at
 System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

这里有2个想法

首先,如果您的强类使用 _id 作为整数,则不能将 shell 与 ObjectId 一起使用(默认)。 尝试:

db.queries.insert { ... } id:int

现在,您的文档将使用自动 ID 作为Int32 ( _id: 1 ) 插入。 这将避免您的映射器错误:

query = queryCollection.Find(x => x.PrintoutIds.Contains(id)).Single();

其次,它关于“包含”关键字。 在 shell 中,“包含”作为String.Contains Shell 使用Query.Contains(string field, string text) 因此,您不能将 Int 作为“文本”传递。

您在 shell 中的查询必须使用=

没有索引

db.queries.find $.PrintoutIds[*] = 1

或者,创建一个索引

db.queries.ensureIndex PrintoutIds 使用 $.PrintoutIds[*]

现在,使用 indexName

db.queries.find PrintoutIds = 1

但是..... 在编写 Linq 表达式时, Contains可以来自String或来自IEnumerable 如果来自String ,则与普通Query.Contains ,但如果来自IEnumerable ,则与Query.EQ一起Query.EQ

// QueryVisitor.cs : 152

// Contains (String): x.Name.Contains("auricio")
else if (method == "Contains" && type == typeof(string))
{
    var value = this.VisitValue(met.Arguments[0], null);

    return Query.Contains(this.GetField(met.Object, prefix), value);
}
// Contains (Enumerable): x.ListNumber.Contains(2)
else if (method == "Contains" && type == typeof(Enumerable))
{
    var field = this.GetField(met.Arguments[0], prefix);
    var value = this.VisitValue(met.Arguments[1], null);

    return Query.EQ(field, value);
}

将类 Query 中的 Id 更改为 Query_Id 并将起作用

public int **Query_Id** { get; set; }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM