繁体   English   中英

EF:在DbContext上禁用AutoDetectChangesEnabled和ProxyCreationEnabled时,从多对多关系中创建/删除关系

[英]EF: Create/Remove relation from Many-to-Many relations when `AutoDetectChangesEnabled` and `ProxyCreationEnabled` are disabled on DbContext

  1. 了解Foo.IdBar.Id如何在不从数据库加载实体的情况下创建它们的关系。

     class Foo { public int Id { get; set; } public Lst<Bar> Bars { get; set; } } class Bar { public int Id { get; set; } public Lst<Foo> Foos { get; set; } } 

    同样在DbContext构造函数中禁用了此配置:

     Configuration.AutoDetectChangesEnabled = false; Configuration.ProxyCreationEnabled = false; Configuration.LazyLoadingEnabled = false; 
  2. 以及如何消除这种关系?


例:

using (var ctx = new DbCtx())
{
    ctx.Configuration.LazyLoadingEnabled = false;
    ctx.Configuration.ProxyCreationEnabled = false;
    ctx.Configuration.AutoDetectChangesEnabled = false;
    ctx.Database.Log += Console.WriteLine;

    var foo = new Foo {Id = 1, Bars = new List<Bar>() };
    var bar = new Bar { Id = 3, Foos = new List<Foo>() };

    // This approach wont work, as AutoDetectChanges are disabled
    ctx.Foos.Attach(foo);
    ctx.Bars.Attach(bar);

    foo.Bars.Add(bar);
    ctx.SaveChanges();
}

如何在不更改配置的情况下定义关系。

先感谢您。

好的,已经找到了解决方案,这是帮助方法:

static void ChangeRelationship<T1, T2>(
    IObjectContextAdapter ctx, 
    T1 a, 
    T2 b, 
    Expression<Func<T1, object>> getNavigationProperty,
    EntityState state) where T1: class
{
    ctx
        .ObjectContext
        .ObjectStateManager
        .ChangeRelationshipState(
            a,
            b,
            getNavigationProperty,
            state
        );
}

并在我的问题示例中使用它:

using (var ctx = new DbCtx())
{
    ctx.Configuration.LazyLoadingEnabled = false;
    ctx.Configuration.ProxyCreationEnabled = false;
    ctx.Configuration.AutoDetectChangesEnabled = false;
    ctx.Database.Log += Console.WriteLine;

    var foo = new Foo {Id = 1, Bars = new List<Bar>()};
    var bar = new Bar { Id = 3, Foos = new List<Foo>() };

    ctx.Entry(foo).State = EntityState.Unchanged;
    ctx.Entry(bar).State = EntityState.Unchanged;

    // create
    ChangeRelationship(ctx, foo, bar, x => x.Bars, EntityState.Added);
    ctx.SaveChanges();

    // remove
    ChangeRelationship(ctx, foo, bar, x => x.Bars, EntityState.Deleted);
    ctx.SaveChanges();
}

如果我理解正确,则希望将Bar对象添加到现有的Foo实体中,而不需要查找Foo实体。

假设您已经有Foo(id = 1)。 想要向其添加新的Bar(id = 100)实体。

using (var context = new Context())
{
    var bar = new Bar() { Id = 100 };
    var foo = new Foo() { Id = 1 }; // Only ID is required

    context.Foos.Attach(foo);
    bar.Foos.Add(foo);

    context.Bars.Add(bar);
    context.SaveChanges();
}

您的要求是可能的。 步骤如下:

(1)首先创建两个仅指定PK的实体实例,然后将其中一个实例(例如foo )附加到上下文:

var foo = new Foo { Id = fooId };
var bar = new Bar { Id = barId };
ctx.Foos.Attach(foo);

(2)将第二个实体集合设置为包含第一个实体的新列表(即“创建”关系):

bar.Foos = new List<Foo> { foo };

(3)标记第二个实体如下:

(A)要添加关系:

ctx.Entry(bar).State = EntityState.Added;

(B)删除关系:

ctx.Entry(bar).State = EntityState.Deleted;

(4)将第二个实体标记为未更改:

ctx.Entry(bar).State = EntityState.Unchanged;

就是这样!

一旦调用ctx.SaveChanges(); ,该关系将在联结表中添加或删除。

更新:尽管上面的方法DbContext.ChangeTracker.DetectChanges()如果我们明确地在末尾调用DbContext.ChangeTracker.DetectChanges() ),我最初的解决方案是将第二个实体附加到“原始”集合上,然后模拟修改也是DbContext.ChangeTracker.DetectChanges() ),但我应该承认ObjectContext您发现的解决方案看起来更加自然(奇怪的是,该功能尚未通过DbContext ),因此我个人投票赞成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM