Azure CosmosDB + EF Core:无法在拥有的属性内使用嵌套集合?

huangapple go评论92阅读模式
英文:

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(OwnedNavigationBuilder2 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&lt;GrandChild&gt; GrandChildren { get; set; }
}

Configured as follows:

modelBuilder.Entity&lt;Root&gt;().OwnsOne(x =&gt; 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&lt;Child&gt;().HasMany(x =&gt; 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, Key
&gt; principalKey, String propertyBaseName, Nullable
1 required,
> ConfigurationSource configurationSource)
> InternalEntityTypeBuilder.HasRelationship(EntityType targetEntityType,
> Nullable1 navigationToTarget, Nullable1 inverseNavigation,
> Nullable1 setTargetAsPrincipal, ConfigurationSource
&gt; configurationSource, Nullable
1 required)
> InternalEntityTypeBuilder.HasOwnership(TypeIdentity& targetEntityType,
> MemberIdentity& navigation, Nullable1 inverse, ConfigurationSource
&gt; configurationSource)
&gt; InternalEntityTypeBuilder.HasOwnership(TypeIdentity&amp; typeIdentity,
&gt; MemberIdentity navigation, ConfigurationSource configurationSource)
&gt; OwnedNavigationBuilder
2.OwnsManyBuilder[TNewRelatedEntity](TypeIdentity
> ownedType, MemberIdentity navigation)
> OwnedNavigationBuilder2.OwnsMany[TNewDependentEntity](Expression1
> navigationExpression)
> <>c.<OnModelCreating>b__13_4(OwnedNavigationBuilder2 cb) line 39
&gt; EntityTypeBuilder
1.OwnsOne[TRelatedEntity](Expression1
&gt; navigationExpression, Action
1 buildAction)
> 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:
Azure CosmosDB + EF Core:无法在拥有的属性内使用嵌套集合?

Azure CosmosDB + EF Core:无法在拥有的属性内使用嵌套集合?

Explanation:

  • Initially define the Entities such as Root, Child, and GrandChild.

  • YourDbContext class derives from DbContext, which Entity Framework Core provides for interacting with databases.

  • The Roots property is a DbSet that represents the database's collection of Root entities.

  • OnConfiguring and OnModelCreating configures connection details and the relationship between Root, Child, and GrandChild respectively.

  • The two GrandChild entities are added to the collection of GrandChildren of 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 OwnsOne and OwnsMany methods in the OnModelCreating method assist in defining the ownership connections between entities. One Child belongs to The Root, and that Child belongs to numerous GrandChild entities.

  • 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&lt;Root&gt; Roots {get; set;}

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        var endpoint = &quot;*****&quot;;
        var key = &quot;******&quot;;
        var databaseName = &quot;nestedDb&quot;;

        optionsBuilder.UseCosmos(endpoint, key, databaseName);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity&lt;Root&gt;().OwnsOne(x =&gt; x.Child, cb =&gt;
        {
            cb.OwnsMany(c =&gt; c.GrandChildren);
        });
    }
}

class Program
{
    static void Main(string[] args)
    {
        using (var dbContext = new YourDbContext())
        {
            dbContext.Database.EnsureCreated();

            var grandChild1 = new GrandChild { Id = 1, Name = &quot;Pavan&quot;, Age = 25 };
            var grandChild2 = new GrandChild { Id = 2, Name = &quot;Balaji&quot;, Age = 20 };

            var child = new Child
            {
                GrandChildren = new List&lt;GrandChild&gt; { grandChild1, grandChild2 }
            };

            var root = new Root
            {
                Child = child
            };

            dbContext.Roots.Add(root);
            dbContext.SaveChanges();

            Console.WriteLine(&quot;Root and related entities saved to Cosmos DB.&quot;);
        }
    }
}

Output:
Azure CosmosDB + EF Core:无法在拥有的属性内使用嵌套集合?

Azure CosmosDB + EF Core:无法在拥有的属性内使用嵌套集合?

Explanation:

  • Initially define the Entities such as Root, Child and GrandChild.

  • YourDbContext class derives from DbContext, which Entity Framework Core provides for interacting with databases.

  • The Roots property is a DbSet that represents the database's collection of Root entities.

  • OnConfiguring and OnModelCreating configures connection details and relationship between Root, Child, and GrandChild respectively.

  • The two GrandChild entities are added to the collection of GrandChildren of 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 OwnsOne and OwnsMany methods in the OnModelCreating method assist in defining the ownership connections between entities. One Child belongs to The Root, and that Child belongs to numerous GrandChild entities.

  • For further please refer this link.

huangapple
  • 本文由 发表于 2023年7月31日 20:54:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76803843.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定