gpt4 book ai didi

entity-framework - EF CTP5 无法更新可选导航属性

转载 作者:行者123 更新时间:2023-12-03 01:22:14 25 4
gpt4 key购买 nike

“项目”和"template"之间存在多对一关联。

项目具有"template"类型的属性。

关联不是双向的("template"不了解“项目”)。

我的“项目”关联实体映射是:

this.HasOptional(p => p.Template);

如果我在没有指定模板的情况下创建“项目”,则 null 会正确插入到“项目”表的“TemplateId”列中。

如果我指定模板,则模板的 ID 会被正确插入。生成的SQL:

update [Projects]
set [Description] = '' /* @0 */,
[UpdatedOn] = '2011-01-16T14:30:58.00' /* @1 */,
[ProjectTemplateId] = '5d2df249-7ac7-46f4-8e11-ad085c127e10' /* @2 */
where (([Id] = '8c1b2d30-b83e-4229-b0c3-fed2e36bf396' /* @3 */)
and [ProjectTemplateId] is null)

但是,如果我尝试更改模板甚至将其设置为 null,则 templateId 不会更新。生成的SQL:

update [Projects]
set [UpdatedOn] = '2011-01-16T14:32:14.00' /* @0 */
where ([Id] = '8c1b2d30-b83e-4229-b0c3-fed2e36bf396' /* @1 */)

如您所见,TemplateId 未更新。

这对我来说毫无意义。我什至尝试在代码中显式地将“Project”的“Template”属性设置为 null,当单步执行代码时,您可以看到它完全没有效果!

谢谢,本

[更新]

最初我认为这是由于我忘记在 DbContext 上添加 IDbSet 属性造成的。然而,现在我已经进一步测试了它,我不太确定。下面是一个完整的测试用例:

public class PortfolioContext : DbContext, IDbContext
{
public PortfolioContext(string connectionStringName) : base(connectionStringName) { }

public IDbSet<Foo> Foos { get; set; }
public IDbSet<Bar> Bars { get; set; }

protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder) {

modelBuilder.Configurations.Add(new FooMap());
modelBuilder.Configurations.Add(new BarMap());

base.OnModelCreating(modelBuilder);
}

public new IDbSet<TEntity> Set<TEntity>() where TEntity : class {
return base.Set<TEntity>();
}
}

public class Foo {
public Guid Id { get; set; }
public string Name { get; set; }
public virtual Bar Bar { get; set; }

public Foo()
{
this.Id = Guid.NewGuid();
}
}

public class Bar
{
public Guid Id { get; set; }
public string Name { get; set; }

public Bar()
{
this.Id = Guid.NewGuid();
}
}

public class FooMap : EntityTypeConfiguration<Foo>
{
public FooMap()
{
this.ToTable("Foos");
this.HasKey(f => f.Id);
this.HasOptional(f => f.Bar);
}
}

public class BarMap : EntityTypeConfiguration<Bar>
{
public BarMap()
{
this.ToTable("Bars");
this.HasKey(b => b.Id);
}
}

测试:

[Test]  
public void Template_Test()
{
var ctx = new PortfolioContext("Portfolio");

var foo = new Foo { Name = "Foo" };
var bar = new Bar { Name = "Bar" };

foo.Bar = bar;

ctx.Set<Foo>().Add(foo);

ctx.SaveChanges();

object fooId = foo.Id;
object barId = bar.Id;

ctx.Dispose();

var ctx2 = new PortfolioContext("Portfolio");
var dbFoo = ctx2.Set<Foo>().Find(fooId);

dbFoo.Bar = null; // does not update

ctx2.SaveChanges();
}

请注意,这是使用 SQL CE 4。

最佳答案

好的,您只需要在对其执行任何操作之前加载导航属性即可。通过加载它,您实际上将其注册到 ObjectStateManager,EF 会通过 ObjectStateManager 来生成更新语句作为 SaveChanges() 的结果。

using (var context = new Context())
{
var dbFoo = context.Foos.Find(fooId);
((IObjectContextAdapter)context).ObjectContext.LoadProperty(dbFoo, f => f.Bar);

dbFoo.Bar = null;
context.SaveChanges();
}

此代码将导致:

exec sp_executesql N'update [dbo].[Foos]
set [BarId] = null
where (([Id] = @0) and ([BarId] = @1))
',N'@0 uniqueidentifier,@1 uniqueidentifier',@0='A0B9E718-DA54-4DB0-80DA-C7C004189EF8',@1='28525F74-5108-447F-8881-EB67CCA1E97F'

关于entity-framework - EF CTP5 无法更新可选导航属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4705991/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com