我需要对也位于另一个容器中的实体进行非规范化:
public class Post
{
public int Id { get; set; }
public string Title { get; set; } = null!;
public List<Hashtag> Hashtags { get; set; } = new List<Hashtag>();
}
public class Comment
{
public int Id { get; set; }
public int PostId { get; set; }
public string Text { get; set; } = null!;
public List<Hashtag> Hashtags { get; set; } = new List<Hashtag>();
}
public class Hashtag
{
public int Id { get; set; }
public string Title { get; set; } = null!;
public int Puntuation { get; set; }
}
因此,为了更快的查询,我需要将
Hashtag
嵌入到 Comment
和 Post
中(这只是一个示例,不是真正的用例),但主题标签位于它自己的容器中。
我知道这在 EF Core 中是不可能的,因为我会看到这样的错误:
“主题标签”类型无法标记为拥有,因为已存在同名的非拥有实体类型。
有什么解决办法吗?
我尝试过做这样的事情:
builder.Entity<Post>().ToContainer("Post");
builder.Entity<Post>().OwnsMany(p => p.Hashtags);
builder.Entity<Comment>().ToContainer("Post");
builder.Entity<Comment>().OwnsMany(p => p.Hashtags);
builder.Entity<Hashtag>().ToContainer("Hashtag");
如何使用 Azure Cosmos Db 对 EF Core 中的数据进行非规范化?
下面是有关如何使用 Azure Cosmos DB 对 EF Core 中的数据进行非规范化的示例。其中
Order
实体包含嵌套实体 Customer
和 OrderDetail
。在 OnModelCreating
方法中,设置实体配置来定义实体在 Cosmos DB 中的存储方式。 OwnsOne
和 OwnsMany
方法用于指定所有权和配置嵌套实体。使用 HasData
方法将样本数据植入数据库。该数据包括 Order
实体及其关联的 Customer
和 OrderDetail
实体。非规范化是通过将相关数据分组到单个文档或容器中来执行的,如下面的输出所示。
public class Order
{
public string id { get; set; }
public DateTime OrderDate { get; set; }
public Customer Customer { get; set; }
public List<OrderDetail> OrderDetails { get; set; }
}
public class Customer
{
public string CustomerId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
public class OrderDetail
{
public string Id { get; set; }
public string OrderId { get; set; }
public string ProductId { get; set; }
public string ProductName { get; set; }
public decimal ProductPrice { get; set; }
public int Quantity { get; set; }
}
public class ECommerceContext : DbContext
{
public DbSet<Order> Orders { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseCosmos(
"<url>",
"<primary_key>",
databaseName: "firstDb");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.OwnsOne(o => o.Customer, customer =>
{
customer.WithOwner().HasForeignKey("OrderId");
customer.Property<string>("CustomerId").IsRequired();
});
modelBuilder.Entity<Order>().OwnsMany(o => o.OrderDetails, od =>
{
od.WithOwner().HasForeignKey("OrderId");
od.Property<string>("Id").IsRequired(); // Ensure Id is required
});
modelBuilder.Entity<Order>()
.ToContainer("Orders")
.HasPartitionKey(o => o.id);
// Seeding the Order entity
modelBuilder.Entity<Order>().HasData(new Order
{
id = "order1",
OrderDate = DateTime.UtcNow
});
// Seeding related Customer entity
modelBuilder.Entity<Order>().OwnsOne(o => o.Customer).HasData(new
{
OrderId = "order1",
CustomerId = "customer1",
Name = "Pavan Sai",
Email = "[email protected]"
});
// Seeding related OrderDetail entities
modelBuilder.Entity<Order>().OwnsMany(o => o.OrderDetails).HasData(
new
{
Id = "orderdetail1",
OrderId = "order1",
ProductId = "product1",
ProductName = "Product 1",
ProductPrice = 10.0m,
Quantity = 2
},
new
{
Id = "orderdetail2",
OrderId = "order1",
ProductId = "product2",
ProductName = "Product 2",
ProductPrice = 20.0m,
Quantity = 1
}
);
}
}
输出:
List of Orders:
Order ID: order1
Order ID: order1
Order Date: 5/29/2024 10:06:45 AM
Customer ID: customer1
Customer Name: Pavan Sai
Customer Email: [email protected]
Product ID: product1
Product Name: Product 1
Product Price: $10.00
Quantity: 2
Product ID: product2
Product Name: Product 2
Product Price: $20.00
Quantity: 1