如何将 mongo bson 数组映射到 c# 对象,然后使用 Entity framework 保存在 SQL 中
How to map mongo bson array to c# object , then save in SQL using Entity framework
我有一个具有以下结构的 mongodb bson 集合,credentials[] 导致了问题,你能推荐一个解决方案吗?我有设备 class 并且有 entity framework 的导航 属性。还设置了上下文,只是 json 数组导致了问题,因为它内部有字符串而不是文档。
Bson文档
{
"_id" : ObjectId("592dbf1446dbac785d6556a5"),
"deviceName" : "Computer1",
"updated" : ISODate("2017-06-30T20:18:25.681Z"),
"credentials" : [
"fa4bafad-51b0-494c-89d8-6154f23bf3af",
"3138ac95-b9e6-4dbe-9825-f109c0d47f67"
],
"lastActivity" : ISODate("2017-06-06T17:55:35.894Z"),
"clientVersion" : "2.14.0"
}
C#classes
public class Device
{
[Key]
public string _id { get; set; }
public string deviceName { get; set; }
public DateTime? updated { get; set; }
public string clientVersion { get; set; }
public DateTime lastActivity { get; set; }
public ICollection <Credentials> credentials { get; set; }
}
public class Credentials
{
[Key]
public Guid CredentialId { get; set; }
public string credentials { get; set; }
[ForeignKey("Device")]
public string DeviceId { get; set; }
public virtual Device Device { get; set; }
}
using (var context = new GkDataContext())
{
var deviceCollection = await Db.GetCollection<Device>("Devices").Find(new BsonDocument()).ToListAsync();
context.device.AddRange(deviceCollection);
context.SaveChanges();
}
好的,您的 EF 实体是查看 Mongo 对象,还是仅查看 SQL 服务器 table 记录?
您的 Mongo 实体(或对象)将只有字符串集合。我希望将未映射的 GUID 集合添加到解析 Mongo 对象的 类 中。要在 SQL 端处理对 Credential table 的实体引用,我希望针对这些 ID 执行 SelectMany,然后从 SQL 服务器预加载 Credential 实体以提供匹配添加到 Device.SQL 实例的引用。
public class MongoDevice
{
...
public ICollection<string> Credentials{ get; set; }
[NotMapped]
public ReadOnlyCollection<Guid> CredentialIds
{ // Can be optimized, but requires coding to keep in sync with operations against Credentials...
get{ return Credentials.Select(x=> Guid.Parse(x)).ToList().AsReadOnly(); }
}
}
public class Device
{
...
public virtual List<Credential> Credentials{ get; set; }
}
您可能一直在考虑拥有一个可以在 Mongo 和 SQL 之间切换的实体?我认为这不实用,因为您希望 SQL 中的 object/table 引用用于凭据,Mongo 不提供这些。
加载 Mongo 个实体并收集凭据 ID 后...
// If you have a lot of devices / credentials, break this up into several iterations. You don't want to end up with a huge IN clause below.
List<Guid> credentialIds = mongoDevices.SelectMany(x=> x.CredentialIds).ToList();
List<Credential> credentials = sqlDbContext.Credentials.Where(x=> credentialIds.Contains(x.CredentialId)).ToList();
现在,当您将 Mongo 设备转置为 SQL 记录设备时...上面的提示是此时 mongoDevices 必须是内存中的集合,因为 EF 不会知道 CredentialIds 是什么。它只是一个助手 属性 来帮助解析到 Guid。
这可以通过多种方式完成,您可以遍历每个设备 (Mongo) 和 load/create SQL 中的对应设备,然后检查凭据 ID 以确保每个被考虑在内,或者它可以在所有记录都应该被考虑的假设下一次处理。上面的 "credentials" 集合将引用 SQL 中的所有凭据记录和一批 ID,一次性获取到 SQL 服务器,而不是按需检索记录。如果预计这是大量的记录,那么要么分成批次,要么从每条记录的按需开始,然后从那里开始工作。
我有一个具有以下结构的 mongodb bson 集合,credentials[] 导致了问题,你能推荐一个解决方案吗?我有设备 class 并且有 entity framework 的导航 属性。还设置了上下文,只是 json 数组导致了问题,因为它内部有字符串而不是文档。 Bson文档
{
"_id" : ObjectId("592dbf1446dbac785d6556a5"),
"deviceName" : "Computer1",
"updated" : ISODate("2017-06-30T20:18:25.681Z"),
"credentials" : [
"fa4bafad-51b0-494c-89d8-6154f23bf3af",
"3138ac95-b9e6-4dbe-9825-f109c0d47f67"
],
"lastActivity" : ISODate("2017-06-06T17:55:35.894Z"),
"clientVersion" : "2.14.0"
}
C#classes
public class Device
{
[Key]
public string _id { get; set; }
public string deviceName { get; set; }
public DateTime? updated { get; set; }
public string clientVersion { get; set; }
public DateTime lastActivity { get; set; }
public ICollection <Credentials> credentials { get; set; }
}
public class Credentials
{
[Key]
public Guid CredentialId { get; set; }
public string credentials { get; set; }
[ForeignKey("Device")]
public string DeviceId { get; set; }
public virtual Device Device { get; set; }
}
using (var context = new GkDataContext())
{
var deviceCollection = await Db.GetCollection<Device>("Devices").Find(new BsonDocument()).ToListAsync();
context.device.AddRange(deviceCollection);
context.SaveChanges();
}
好的,您的 EF 实体是查看 Mongo 对象,还是仅查看 SQL 服务器 table 记录?
您的 Mongo 实体(或对象)将只有字符串集合。我希望将未映射的 GUID 集合添加到解析 Mongo 对象的 类 中。要在 SQL 端处理对 Credential table 的实体引用,我希望针对这些 ID 执行 SelectMany,然后从 SQL 服务器预加载 Credential 实体以提供匹配添加到 Device.SQL 实例的引用。
public class MongoDevice
{
...
public ICollection<string> Credentials{ get; set; }
[NotMapped]
public ReadOnlyCollection<Guid> CredentialIds
{ // Can be optimized, but requires coding to keep in sync with operations against Credentials...
get{ return Credentials.Select(x=> Guid.Parse(x)).ToList().AsReadOnly(); }
}
}
public class Device
{
...
public virtual List<Credential> Credentials{ get; set; }
}
您可能一直在考虑拥有一个可以在 Mongo 和 SQL 之间切换的实体?我认为这不实用,因为您希望 SQL 中的 object/table 引用用于凭据,Mongo 不提供这些。
加载 Mongo 个实体并收集凭据 ID 后...
// If you have a lot of devices / credentials, break this up into several iterations. You don't want to end up with a huge IN clause below.
List<Guid> credentialIds = mongoDevices.SelectMany(x=> x.CredentialIds).ToList();
List<Credential> credentials = sqlDbContext.Credentials.Where(x=> credentialIds.Contains(x.CredentialId)).ToList();
现在,当您将 Mongo 设备转置为 SQL 记录设备时...上面的提示是此时 mongoDevices 必须是内存中的集合,因为 EF 不会知道 CredentialIds 是什么。它只是一个助手 属性 来帮助解析到 Guid。
这可以通过多种方式完成,您可以遍历每个设备 (Mongo) 和 load/create SQL 中的对应设备,然后检查凭据 ID 以确保每个被考虑在内,或者它可以在所有记录都应该被考虑的假设下一次处理。上面的 "credentials" 集合将引用 SQL 中的所有凭据记录和一批 ID,一次性获取到 SQL 服务器,而不是按需检索记录。如果预计这是大量的记录,那么要么分成批次,要么从每条记录的按需开始,然后从那里开始工作。