将带有id的api中的OData实体保存到实体框架中的数据库中
本文关键字:实体 保存 框架 数据库 中的 id api OData | 更新日期: 2023-09-27 18:14:06
我有多个项目,它们通过API端点返回相同的OData实体。现在我想调用所有的项目,并将它们存储在我的调用项目数据库与实体框架。
将它们添加到数据库的ID被覆盖,但我想保存的ID,实体在项目数据库中也有。所以如果需要的话,我仍然可以访问它们,并检查数据是否已经在我的数据库中。因此,我需要在实体中添加另一个MainProjectID和projectID列。
我试着做一个新的类,有一个引用的实体,我想保存,但这使用新的id的实体。我也尝试继承类,但这给了我关键的冲突问题,和泛型不工作在实体框架(我不是说他们应该)。所以我现在有点不知所措。
我基本上想将id保存为非键。有没有办法,我可以做到这一点,而不编写全新的类和解析他们手动?
任何帮助都将非常感激。
我们有多个选择:
-
在分布式系统中,处理这类ID冲突的最好方法是使ID全局唯一。如果你能修改id的生成方式,那就是我的选择。您可以使用UUID(或Microsoft实现GUID)来生成通用唯一标识符。或者,如果这看起来有点小题大做,你可以设计一个简单的机制,将ID与projectID结合起来。然而,你应该确保你将使用的方法不会产生任何冲突(没有两个不同的id-projectId对将映射到相同的值)。
这将确保在整个应用程序中使用相同的实体,并且如果您尝试将来自不同来源的记录放入同一表中,则不会发生重叠。您只需要实现一种机制来记录哪个ID来自哪个源。您可以在聚合器中使用引用实体来实现此目的。您还需要禁用ID列的自动递增特性,以便在表中使用您的全局惟一值。
-
您可以使用不同的实体来生成和聚合应用程序。我不知道你的应用程序,但这对我来说似乎是一个好的方法,因为聚合应用程序对实体有不同的想法。聚合应用程序关心哪个应用程序产生了实体,这可能使得将源应用程序标识符放入条目是合理的。你的实体只会有所不同,当你从API接收到OData对象时,你需要复制所有其他属性并自己放置项目标识符。
-
您可以使用前面的解决方案,但您可以使用派生类,以便不重复您的对象属性。这是一个更好的设计选择。但是,使用这种方法,主键会出现一些问题(正如您所说的那样)。考虑以下示例
public class Base { public int ID { get; set; } [Required] [StringLength(50)] [Display(Name = "Name")] public string Name { get; set; } } public class Derived : Base { [Key] public int projectId {get; set; } }
如果你不把
来实现这一点[Key]
放到Derived,那么你将只有ID
作为主键。当你把[Key]
放到Derived时,你将只有projectId
作为主键。您需要定义一个组合键,您可以通过从projectId
中删除[Key]
注释并使用onModelCreating
覆盖DbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Derived>().HasKey(a => new { a.ID, a.projectId }) .Property(c => c.ID).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None); modelBuilder.Entity<Derived>().Property(c => c.projectId).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None); }
-
您可以混合使用这些选项。您可以删除ID字段上的主键,然后您可以插入一个新的Entity,它将在ID和项目ID之间建模1-M关系。