35

I have following entities in my DbContext:

enter image description here

public class A
{
   public A()
   {
       Bs = new List<B>(); 
   }

   public ICollection<B> Bs { set; get; }
}   

Sometimes I Want to update a graph:

var a = dbContext.As
       .AsNoTracking()
       .Include(x=>x.Bs)
       .firstOrDefault();

var c = new C();
a.Bs.Add(c);

var d = new D();
var e1 = new E();
var e2 = new E();
d.Es.Add(e1); //<-- added new E
d.Es.Add(e2); //<-- added new E

a.Bs.Add(d);

I want to update a with its Bs(update C,D,E too) using graphdiff:

dbContext.UpdateGraph(a,map=>map.OwnedCollection(x=>x.Bs));

This updates A, Bs, Cs, Ds, but not Es.

So I think, I need to define a conditional mapping for graphdiff, to update Es too, somethings like:

dbContext.UpdateGraph(a,map=>map.OwnedCollection(x=>x.Bs.OfType<D>(), 
                                             with =>with.OwnedCollection(t=>t.Es))
                                .OwnedCollection(x=>x.Bs.OfType<C>()));

Is there any way to do this job?

1
  • In the dbContext have you stated that the d 'owns' the collection Es ? something like dbContext.UpdateGraph(d,map=>map.OwnedCollection(x=>x.Es)); ? Commented Sep 15, 2015 at 12:13

2 Answers 2

1

You can use this with graphdiff:

dbContext.UpdateGraph(a, map => map
    .OwnedCollection(b => p.Bs, with => with
    .AssociatedCollection(p => p.Es)));

see this link: GraphDiff Explanation

Sign up to request clarification or add additional context in comments.

Comments

0

I don't believe that is possible using your current class structure. However, I found a way to accomplish this, but you have to make some changes in your code.

Update the A:

public class A
{
   public A()
   {
       Cs = new List<C>(); 
       Ds = new List<D>(); 
   }

   //PK
   public int AId { get; set; }

   public ICollection<C> Cs { set; get; }
   public ICollection<D> Ds { set; get; }       
} 

Update B, C, and D:

public class B
{
    public int BId { get; set; }
}

public class C : B
{
    //FK that links C to A
    public int FK_C_AId { get; set; }
}

public class D : B
{
    //FK that links D to A
    public int FK_D_AId { get; set; }

    public ICollection<E> Es { get; set; }

    public D()
    {
        Es = new List<E>();
    }
}

In order to maintain the TPH strategy, some mappings are necessary.

modelBuilder.Entity<A>()
    .HasMany(i => i.Cs)
    .WithRequired()
    .HasForeignKey(i => i.FK_C_AId)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<A>()
    .HasMany(i => i.Ds)
    .WithRequired()
    .HasForeignKey(i => i.FK_D_AId)
    .WillCascadeOnDelete(false);

modelBuilder.Entity<B>()
    .Map<C>(m => m.Requires("Discriminator").HasValue("C"))
    .Map<D>(m => m.Requires("Discriminator").HasValue("D"));

Now, you have almost the same database structure. C and D are still mapped to the same table.

Finally, update the Graph:

context.UpdateGraph(a, map => map
    .OwnedCollection(b => b.Cs)
    .OwnedCollection(b => b.Ds, with => with
        .AssociatedCollection(e => e.Es)));

Hope it helps!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.