英文:
Azure CosmosDb + EF Core: Can't use embedded collections inside owned properties?
问题
我们正在使用Cosmos DB和EF Core。
我们有一个如下所示的模型:
class Root
{
public Child? Child { get; set; }
}
class Child
{
public List<GrandChild> GrandChildren { get; set; }
}
配置如下:
modelBuilder.Entity<Root>().OwnsOne(x => x.Child);
然而,我无法弄清楚如何配置所拥有的属性Child内部的GrandChildren数组。
没有任何配置的情况下,我收到以下错误:
System.InvalidOperationException:无法确定由类型
List<GrandChild>表示的导航Child.GrandChildren的关系。要么手动配置关系,要么使用[NotMapped]属性或在OnModelCreating中使用EntityTypeBuilder.Ignore来忽略此属性。
尝试添加配置后:
modelBuilder.Entity<Child>().HasMany(x => x.GrandChildren);
现在我面临不同的错误:
System.NullReferenceException:对象引用未设置为对象的实例。
堆栈跟踪:
InternalEntityTypeBuilder.CreateForeignKey(InternalEntityTypeBuilder
principalEntityTypeBuilder, IReadOnlyList1 dependentProperties, Key principalKey, String propertyBaseName, Nullable1 required,
ConfigurationSource configurationSource)
InternalEntityTypeBuilder.HasRelationship(EntityType targetEntityType,
Nullable1 navigationToTarget, Nullable1 inverseNavigation,
Nullable1 setTargetAsPrincipal, ConfigurationSource configurationSource, Nullable1 required)
InternalEntityTypeBuilder.HasOwnership(TypeIdentity& targetEntityType,
MemberIdentity& navigation, Nullable1 inverse, ConfigurationSource configurationSource) InternalEntityTypeBuilder.HasOwnership(TypeIdentity& typeIdentity, MemberIdentity navigation, ConfigurationSource configurationSource) OwnedNavigationBuilder2.OwnsManyBuilder[TNewRelatedEntity](TypeIdentity
ownedType, MemberIdentity navigation)
OwnedNavigationBuilder2.OwnsMany[TNewDependentEntity](Expression1
navigationExpression)
<c.b__13_4(OwnedNavigationBuilder 2 cb) line 39 EntityTypeBuilder1.OwnsOne[TRelatedEntity](Expression1 navigationExpression, Action1 buildAction)
ConfigurationDbContext.OnModelCreating(ModelBuilder
modelBuilder) line 32 ModelCustomizer.Customize(ModelBuilder
modelBuilder, DbContext context)
显然,这是EF Core用于Cosmos DB的提供程序的一个限制,拥有的项目不能拥有自己的拥有属性?
英文:
We're using Cosmos db with EF Core.
We have a model like this:
class Root
{
public Child? Child { get; set; }
}
class Child
{
public List<GrandChild> GrandChildren { get; set; }
}
Configured as follows:
modelBuilder.Entity<Root>().OwnsOne(x => x.Child);
However, I can't figure out how to configure the GrandChildren array within the owned property Child.
Without any configuration, I get this error:
> System.InvalidOperationException : Unable to determine the relationship represented by navigation 'Child.GrandChildren' of type 'List<GrandChild>'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
After attempting to add configuration:
modelBuilder.Entity<Child>().HasMany(x => x.GrandChildren);
Now I face a different error:
> System.NullReferenceException : Object reference not set to an instance of an object.
>
> Stack Trace:
> InternalEntityTypeBuilder.CreateForeignKey(InternalEntityTypeBuilder
> principalEntityTypeBuilder, IReadOnlyList1 dependentProperties, Key1 required,
> principalKey, String propertyBaseName, Nullable
> ConfigurationSource configurationSource)
> InternalEntityTypeBuilder.HasRelationship(EntityType targetEntityType,
> Nullable1 navigationToTarget, Nullable1 inverseNavigation,
> Nullable1 setTargetAsPrincipal, ConfigurationSource1 required)
> configurationSource, Nullable
> InternalEntityTypeBuilder.HasOwnership(TypeIdentity& targetEntityType,
> MemberIdentity& navigation, Nullable1 inverse, ConfigurationSource2.OwnsManyBuilder[TNewRelatedEntity](TypeIdentity
> configurationSource)
> InternalEntityTypeBuilder.HasOwnership(TypeIdentity& typeIdentity,
> MemberIdentity navigation, ConfigurationSource configurationSource)
> OwnedNavigationBuilder
> ownedType, MemberIdentity navigation)
> OwnedNavigationBuilder2.OwnsMany[TNewDependentEntity](Expression1
> navigationExpression)
> <>c.<OnModelCreating>b__13_4(OwnedNavigationBuilder2 cb) line 391.OwnsOne[TRelatedEntity](Expression
> EntityTypeBuilder11 buildAction)
> navigationExpression, Action
> ConfigurationDbContext.OnModelCreating(ModelBuilder
> modelBuilder) line 32 ModelCustomizer.Customize(ModelBuilder
> modelBuilder, DbContext context)
Apparently this is a limitation of EF Core provider for cosmosdb that owned items cannot have owned properties of their own?
答案1
得分: 1
I can't figure out how to configure the GrandChildren array within the owned property Child.
I tried with the below code which stores GrandChildren array within the owned property Child.
public class YourDbContext : DbContext
{
public DbSet<Root> Roots {get; set;}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var endpoint = "*****";
var key = "******";
var databaseName = "nestedDb";
optionsBuilder.UseCosmos(endpoint, key, databaseName);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Root>().OwnsOne(x => x.Child, cb =>
{
cb.OwnsMany(c => c.GrandChildren);
});
}
}
class Program
{
static void Main(string[] args)
{
using (var dbContext = new YourDbContext())
{
dbContext.Database.EnsureCreated();
var grandChild1 = new GrandChild { Id = 1, Name = "Pavan", Age = 25 };
var grandChild2 = new GrandChild { Id = 2, Name = "Balaji", Age = 20 };
var child = new Child
{
GrandChildren = new List<GrandChild> { grandChild1, grandChild2 }
};
var root = new Root
{
Child = child
};
dbContext.Roots.Add(root);
dbContext.SaveChanges();
Console.WriteLine("Root and related entities saved to Cosmos DB.");
}
}
}
Output:


Explanation:
-
Initially define the Entities such as Root, Child, and GrandChild.
-
YourDbContextclass derives fromDbContext, which Entity Framework Core provides for interacting with databases. -
The
Rootsproperty is aDbSetthat represents the database's collection of Root entities. -
OnConfiguringandOnModelCreatingconfigures connection details and the relationship betweenRoot,Child, andGrandChildrespectively. -
The two
GrandChildentities are added to the collection ofGrandChildrenof a Child entity. -
The Child entity is allocated to the Child property of the Root object.
-
The data is saved to the Cosmos DB database by using the
dbContext.SaveChanges()function. -
The
OwnsOneandOwnsManymethods in theOnModelCreatingmethod assist in defining the ownership connections between entities. One Child belongs to The Root, and that Child belongs to numerousGrandChildentities. -
For further details, please refer to this link.
英文:
>I can't figure out how to configure the GrandChildren array within the owned property Child.
I tried with the below code which stores GrandChildren array within the owned property Child.
public class YourDbContext : DbContext
{
public DbSet<Root> Roots {get; set;}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var endpoint = "*****";
var key = "******";
var databaseName = "nestedDb";
optionsBuilder.UseCosmos(endpoint, key, databaseName);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Root>().OwnsOne(x => x.Child, cb =>
{
cb.OwnsMany(c => c.GrandChildren);
});
}
}
class Program
{
static void Main(string[] args)
{
using (var dbContext = new YourDbContext())
{
dbContext.Database.EnsureCreated();
var grandChild1 = new GrandChild { Id = 1, Name = "Pavan", Age = 25 };
var grandChild2 = new GrandChild { Id = 2, Name = "Balaji", Age = 20 };
var child = new Child
{
GrandChildren = new List<GrandChild> { grandChild1, grandChild2 }
};
var root = new Root
{
Child = child
};
dbContext.Roots.Add(root);
dbContext.SaveChanges();
Console.WriteLine("Root and related entities saved to Cosmos DB.");
}
}
}
Output:


Explanation:
-
Initially define the Entities such as Root, Child and GrandChild.
-
YourDbContextclass derives fromDbContext, which Entity Framework Core provides for interacting with databases. -
The
Rootsproperty is aDbSetthat represents the database's collection of Root entities. -
OnConfiguringandOnModelCreatingconfiguresconnectiondetails and relationship betweenRoot,Child, andGrandChildrespectively. -
The two
GrandChildentities are added to the collection ofGrandChildrenof a Child entity. -
The Child entity is allocated to the Child property of the Root object.
-
The data is saved to the Cosmos DB database by using the dbContext.SaveChanges() function.
-
The
OwnsOneandOwnsManymethods in theOnModelCreatingmethod assist in defining the ownership connections between entities. One Child belongs to The Root, and that Child belongs to numerousGrandChildentities. -
For further please refer this link.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论