- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在创建一个 ASP.NET Web API 来在 MongoDB 数据库中执行 CRUD 操作。我已经能够根据以下 Microsoft 教程创建一个简单的应用程序:Create a web API with ASP.NET Core and MongoDB .
本教程和我发现的其他教程一样,都使用定义的数据模型(在上面的教程中是 Book 模型)。在我的例子中,我需要使用通用 JSON 对象执行 CRUD 操作。例如,JSON 对象可能是以下任何示例:
示例#1:
{_id: 1, name: 'Jon Snow', address: 'Castle Black', hobbies: 'Killing White Walkers'}
示例 #2:
{_id: 2, name: 'Daenerys Targaryen', family: 'House Targaryen', titles: ['Queen of Meereen', 'Khaleesi of the Great Grass Sea', 'Mother of Dragons', 'The Unburnt', 'Breaker of Chains', 'Queen of the Andals and the First Men', 'Protector of the Seven Kingdoms', 'Lady of Dragonstone']}
我使用 NoSQL 数据库 (MongoDB) 的原因主要是因为未定义的数据结构,以及仅使用 JSON 执行 CRUD 操作的能力。
作为尝试和错误尝试,我用“对象”和“动态”替换了“书籍”模型,但我遇到了关于转换类型和未知属性的各种错误:
public class BookService
{
private readonly IMongoCollection<object> _books;
public BookService(IBookstoreDatabaseSettings settings)
{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);
_books = database.GetCollection<object>(settings.BooksCollectionName);
}
public List<object> Get() => _books.Find(book => true).ToList();
//public object Get(string id) => _books.Find<object>(book => book.Id == id).FirstOrDefault();
//public object Create(object book)
//{
// _books.InsertOne(book);
// return book;
//}
//public void Update(string id, object bookIn) => _books.ReplaceOne(book => book.Id == id, bookIn);
//public void Remove(object bookIn) => _books.DeleteOne(book => book.Id == bookIn.Id);
//public void Remove(string id) => _books.DeleteOne(book => book.Id == id);
}
错误:
'object' does not contain a definition for 'Id' and no accessible extension method 'Id' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
InvalidCastException: Unable to cast object of type 'd__51' to type 'System.Collections.IDictionaryEnumerator'.
所以,我的问题是,如何将通用 JSON 数据类型与 ASP.NET Core Web API 和 MongoDB 驱动程序一起使用?
更新:基于@pete-garafano suggestion ,我决定继续使用 POCO 模型。
我找到了一个 article in MongoDB's Github解释如何通过 ASP.NET Core 驱动程序使用静态和动态数据的页面。所以我对 Book 模型进行了以下更改:
public class Book
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
public string Author { get; set; }
[BsonExtraElements]
public BsonDocument Metadata { get; set; } //new property
}
现在我面临其他问题,如果我的数据格式与模型完全相同,我就能够列出数据并在数据库中创建新条目。但是,如果我尝试使用以下格式创建一个新条目,则会出现错误:
{
"Name": "test 5",
"Price": 19,
"Category": "Computers",
"Author": "Ricky",
"Metadata": {"Key": "Value"} //not working with this new field
}
System.InvalidCastException: Unable to cast object of type 'MongoDB.Bson.BsonElement' to type 'MongoDB.Bson.BsonDocument'.
此外,如果我在 Mongo 中更改一个条目的数据格式,然后尝试列出所有结果,我会得到同样的错误:
System.InvalidCastException: Unable to cast object of type 'MongoDB.Bson.BsonDocument' to type 'MongoDB.Bson.BsonBoolean'.
基于Mongo documents ,BsonExtraElements 应该允许将通用/动态数据附加到模型。我在新方法中做错了什么?
更新 #2:添加了错误的详细堆栈跟踪
System.InvalidCastException: Unable to cast object of type 'MongoDB.Bson.BsonDocument' to type 'MongoDB.Bson.BsonBoolean'. at get_AsBoolean(Object ) at System.Text.Json.JsonPropertyInfoNotNullable`4.OnWrite(WriteStackFrame& current, Utf8JsonWriter writer) at System.Text.Json.JsonPropertyInfo.Write(WriteStack& state, Utf8JsonWriter writer) at System.Text.Json.JsonSerializer.HandleObject(JsonPropertyInfo jsonPropertyInfo, JsonSerializerOptions options, Utf8JsonWriter writer, WriteStack& state) at System.Text.Json.JsonSerializer.WriteObject(JsonSerializerOptions options, Utf8JsonWriter writer, WriteStack& state) at System.Text.Json.JsonSerializer.Write(Utf8JsonWriter writer, Int32 originalWriterDepth, Int32 flushThreshold, JsonSerializerOptions options, WriteStack& state) at System.Text.Json.JsonSerializer.WriteAsyncCore(Stream utf8Json, Object value, Type inputType, JsonSerializerOptions options, CancellationToken cancellationToken) at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
更新 #3:添加了 Book 服务和 Controller 代码文件、数据库 Book 集合和在 get() 结果中启动的异常。
图书服务.cs:
public class BookService
{
private readonly IMongoCollection<Book> _books;
public BookService(IBookstoreDatabaseSettings settings)
{
var client = new MongoClient(settings.ConnectionString);
var database = client.GetDatabase(settings.DatabaseName);
_books = database.GetCollection<Book>(settings.BooksCollectionName);
}
public List<Book> Get() => _books.Find(book => true).ToList();
public Book Get(string id) => _books.Find<Book>(book => book.Id == id).FirstOrDefault();
public Book Create(Book book)
{
_books.InsertOne(book);
return book;
}
public void Update(string id, Book bookIn) => _books.ReplaceOne(book => book.Id == id, bookIn);
public void Remove(Book bookIn) => _books.DeleteOne(book => book.Id == bookIn.Id);
public void Remove(string id) => _books.DeleteOne(book => book.Id == id);
}
BooksController.cs:
[Route("api/[controller]")]
[ApiController]
public class BooksController : ControllerBase
{
private readonly BookService _bookService;
public BooksController(BookService bookService)
{
_bookService = bookService;
}
[HttpGet]
public ActionResult<List<Book>> Get() => _bookService.Get(); // error happens when executing Get()
[HttpGet("{id:length(24)}", Name = "GetBook")]
public ActionResult<Book> Get(string id)
{
var book = _bookService.Get(id);
if (book == null)
{
return NotFound();
}
return book;
}
[HttpPost]
public ActionResult<Book> Create([FromBody] Book book)
{
_bookService.Create(book);
return CreatedAtRoute("GetBook", new { id = book.Id.ToString() }, book);
}
[HttpPut("{id:length(24)}")]
public IActionResult Update(string id, Book bookIn)
{
var book = _bookService.Get(id);
if (book == null)
{
return NotFound();
}
_bookService.Update(id, bookIn);
return NoContent();
}
[HttpDelete("{id:length(24)}")]
public IActionResult Delete(string id)
{
var book = _bookService.Get(id);
if (book == null)
{
return NotFound();
}
_bookService.Remove(book.Id);
return NoContent();
}
}
BookstoreDb.Books:
//non-pretty
{ "_id" : ObjectId("5df2b193405b7e9c1efa286f"), "Name" : "Design Patterns", "Price" : 54.93, "Category" : "Computers", "Author" : "Ralph Johnson" }
{ "_id" : ObjectId("5df2b193405b7e9c1efa2870"), "Name" : "Clean Code", "Price" : 43.15, "Category" : "Computers", "Author" : "Robert C. Martin" }
{ "_id" : ObjectId("5df2b1c9fe91da06078d9fbb"), "Name" : "A New Test", "Price" : 43.15, "Category" : "Computers", "Author" : "Ricky", "Metadata" : { "Key" : "Value" } }
Mongo Driver 的详细结果:
[/0]:{Api.Models.Book} Author [string]:"Ralph Johnson" Category [string]:"Computers" Id [string]:"5df2b193405b7e9c1efa286f" Metadata [BsonDocument]:null Name [string]:"Design Patterns" Price [decimal]:54.93
[/1]:{Api.Models.Book} Author [string]:"Robert C. Martin" Category [string]:"Computers" Id [string]:"5df2b193405b7e9c1efa2870" Metadata [BsonDocument]:null Name [string]:"Clean Code" Price [decimal]:43.15
[/2]:{Api.Models.Book} Author [string]:"Ricky" Category [string]:"Computers" Id [string]:"5df2b1c9fe91da06078d9fbb" Metadata [BsonDocument]:{{ "Metadata" : { "Key" : "Value" } }} AllowDuplicateNames [bool]:false AsBoolean [bool]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBoolean' threw an exception of type 'System.InvalidCastException' AsBsonArray [BsonArray]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonArray' threw an exception of type 'System.InvalidCastException' AsBsonBinaryData [BsonBinaryData]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonBinaryData' threw an exception of type 'System.InvalidCastException' AsBsonDateTime [BsonDateTime]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonDateTime' threw an exception of type 'System.InvalidCastException' AsBsonDocument [BsonDocument]:{{ "Metadata" : { "Key" : "Value" } }} AsBsonJavaScript [BsonJavaScript]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonJavaScript' threw an exception of type 'System.InvalidCastException' AsBsonJavaScriptWithScope [BsonJavaScriptWithScope]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonJavaScriptWithScope' threw an exception of type 'System.InvalidCastException' AsBsonMaxKey [BsonMaxKey]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonMaxKey' threw an exception of type 'System.InvalidCastException' AsBsonMinKey [BsonMinKey]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonMinKey' threw an exception of type 'System.InvalidCastException' AsBsonNull [BsonNull]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonNull' threw an exception of type 'System.InvalidCastException' AsBsonRegularExpression [BsonRegularExpression]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonRegularExpression' threw an exception of type 'System.InvalidCastException' AsBsonSymbol [BsonSymbol]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonSymbol' threw an exception of type 'System.InvalidCastException' AsBsonTimestamp [BsonTimestamp]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonTimestamp' threw an exception of type 'System.InvalidCastException' AsBsonUndefined [BsonUndefined]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsBsonUndefined' threw an exception of type 'System.InvalidCastException' AsBsonValue [BsonValue]:{{ "Metadata" : { "Key" : "Value" } }} AsByteArray [byte[]]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsByteArray' threw an exception of type 'System.InvalidCastException' AsDateTime [DateTime]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsDateTime' threw an exception of type 'System.InvalidCastException' AsDecimal [decimal]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsDecimal' threw an exception of type 'System.InvalidCastException' AsDecimal128 [Decimal128]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsDecimal128' threw an exception of type 'System.InvalidCastException' AsDouble [double]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsDouble' threw an exception of type 'System.InvalidCastException' AsGuid [Guid]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsGuid' threw an exception of type 'System.InvalidCastException' AsInt32 [int]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsInt32' threw an exception of type 'System.InvalidCastException' AsInt64 [long]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsInt64' threw an exception of type 'System.InvalidCastException' AsLocalTime [DateTime]:'(new System.Collections.Generic.ICollectionDebugView(test).Items2).Metadata.AsLocalTime' threw an exception of type 'System.InvalidCastException' [More] Name [string]:"A New Test" Price [decimal]:43.15
最佳答案
您应该使用 BsonDocument
在 C# 中使用 MongoDB 处理非类型化数据。
private readonly IMongoCollection<BsonDocument> _books;
这并不理想,因为 C# 更喜欢强类型的字段名称。我建议尝试为数据构建 POCO 模型以简化查询/更新操作。如果你做不到这一点,你将无法使用像
这样的语法_books.DeleteOne(book => book.Id == id);
您需要改为使用字典类型访问器语法,例如:
_books.DeleteOne(book => book["_id"] == id);
请注意 _id
字段在 MongoDB 中是特殊的,因为它必须出现在每个文档中,并且在集合中是唯一的。在您链接到的示例中,他们提供了一个实体模型。此模型中的 Id
字段有 2 个装饰器
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
这些告诉驱动程序 Id
字段应该用作 _id
,而那个字段,而 C# 中的字符串应该被视为 ObjectId
由 MongoDB 编写。
如果您使用的是完全无类型的模型,则需要注意 _id
和 id
之间的区别,并确保正确映射字段或创建id
上的索引(前者可能是您想要的)。
我写了一个post前一段时间可能对你有帮助。它涵盖了许多与 Microsoft 帖子相同的 Material ,但可能会为您提供更多见解。
虽然您提供的示例数据确实有所不同,但仍然可以创建一个允许您在查询中使用类型信息的 POCO 模型。我建议您研究这样做的可行性以简化您的开发。正如我上面所解释的,这不是必需的,但它肯定会改善查询体验。
BsonExtraElements
属性意味着驱动程序可以反序列化不在模型中的字段。例如,如果您将 Metadata
字段重命名为 Foo
,然后重新运行它。数据库中的 Metadata
字段现在实际上应该包含在 Foo
字段中。
System.InvalidCastException: Unable to cast object of type 'MongoDB.Bson.BsonDocument' to type 'MongoDB.Bson.BsonBoolean'.
此异常似乎表明数据库中有一个 BsonDocument
,但驱动程序试图将其分配给一个 bool
值。我无法重现我这边的错误。正如您在上面提供的那样,我在数据库中创建了一个文档。
您能否提供其余的堆栈跟踪信息?它可能会为我们提供有关哪个字段导致问题的更多信息。您还可以尝试从 POCO 的 Metadata
中删除 BsonExtraElements
并仅为 BsonExtraElements
创建一个新字段。
感谢您提供完整的堆栈跟踪。这让我“啊哈!”片刻。该错误本身并非来自 MongoDB 驱动程序。该错误实际上来自 JSON 序列化程序,因为它访问了 BsonDocument
类型的所有字段。
BsonDocument
是一种惰性类型。在您尝试访问它之前,它不会“知道”它包含什么。这是通过为许多不同的字段提供一个 getter 来处理的,所有这些字段都由它可能包含的类型命名。你可以看到他们here .
ASP 中的 JSON 序列化程序尽职尽责地迭代每个字段(AsBoolean
、AsBsonArray
、AsBsonBinaryData
等)以尝试检索值序列化为 JSON。不幸的是,其中大多数都将失败,因为 Metadata
中的值无法转换为其中的大多数(或任何)。
我认为您需要告诉 JSON 序列化器忽略 Metadata
字段,或者为BsonDocument
.
关于c# - 使用通用 JSON 对象的 .NET Core Web API 和 MongoDB 驱动程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59165779/
我的一位教授给了我们一些考试练习题,其中一个问题类似于下面(伪代码): a.setColor(blue); b.setColor(red); a = b; b.setColor(purple); b
我似乎经常使用这个测试 if( object && object !== "null" && object !== "undefined" ){ doSomething(); } 在对象上,我
C# Object/object 是值类型还是引用类型? 我检查过它们可以保留引用,但是这个引用不能用于更改对象。 using System; class MyClass { public s
我在通过 AJAX 发送 json 时遇到问题。 var data = [{"name": "Will", "surname": "Smith", "age": "40"},{"name": "Wil
当我尝试访问我的 View 中的对象 {{result}} 时(我从 Express js 服务器发送该对象),它只显示 [object][object]有谁知道如何获取 JSON 格式的值吗? 这是
我有不同类型的数据(可能是字符串、整数......)。这是一个简单的例子: public static void main(String[] args) { before("one"); }
嗨,我是 json 和 javascript 的新手。 我在这个网站找到了使用json数据作为表格的方法。 我很好奇为什么当我尝试使用 json 数据作为表时,我得到 [Object,Object]
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我听别人说 null == object 比 object == null check 例如: void m1(Object obj ) { if(null == obj) // Is thi
Match 对象 提供了对正则表达式匹配的只读属性的访问。 说明 Match 对象只能通过 RegExp 对象的 Execute 方法来创建,该方法实际上返回了 Match 对象的集合。所有的
Class 对象 使用 Class 语句创建的对象。提供了对类的各种事件的访问。 说明 不允许显式地将一个变量声明为 Class 类型。在 VBScript 的上下文中,“类对象”一词指的是用
Folder 对象 提供对文件夹所有属性的访问。 说明 以下代码举例说明如何获得 Folder 对象并查看它的属性: Function ShowDateCreated(f
File 对象 提供对文件的所有属性的访问。 说明 以下代码举例说明如何获得一个 File 对象并查看它的属性: Function ShowDateCreated(fil
Drive 对象 提供对磁盘驱动器或网络共享的属性的访问。 说明 以下代码举例说明如何使用 Drive 对象访问驱动器的属性: Function ShowFreeSpac
FileSystemObject 对象 提供对计算机文件系统的访问。 说明 以下代码举例说明如何使用 FileSystemObject 对象返回一个 TextStream 对象,此对象可以被读
我是 javascript OOP 的新手,我认为这是一个相对基本的问题,但我无法通过搜索网络找到任何帮助。我是否遗漏了什么,或者我只是以错误的方式解决了这个问题? 这是我的示例代码: functio
我可以很容易地创造出很多不同的对象。例如像这样: var myObject = { myFunction: function () { return ""; } };
function Person(fname, lname) { this.fname = fname, this.lname = lname, this.getName = function()
任何人都可以向我解释为什么下面的代码给出 (object, Object) 吗? (console.log(dope) 给出了它应该的内容,但在 JSON.stringify 和 JSON.parse
我正在尝试完成散点图 exercise来自免费代码营。然而,我现在只自己学习了 d3 几个小时,在遵循 lynda.com 的教程后,我一直在尝试确定如何在工具提示中显示特定数据。 This code
我是一名优秀的程序员,十分优秀!