【问题标题】:How to not assign an id when id is a fk with a custom id generator in ef当 id 是 ef 中带有自定义 id 生成器的 fk 时如何不分配 id
【发布时间】:2013-03-12 09:09:24
【问题描述】:

我有一个使用 EF5 的项目,我制作了一个自定义 Guid 生成器,并且我重写了 SaveChanges 方法来分配我的实体的 ID。

一切正常,除了一种情况:一个实体的 ID 是另一个实体的另一个 ID 的 FK。

一点代码说明问题:

我有两个无法更改的实体:

public class FixedEntityA
{
    public Guid Id { get; set;}
    public string SomeText { get; set; }
}

public class FixedEntityB
{
    public Guid Id { get; set;}
    public int OneInt { get; set; }
}    

在我的项目中,我有一个这样定义的实体:

public class ComposedEntity
{
    public Guid Id { get; set;}
    public FixedEntityA FixedA { get; set; }
    public FixedEntityB FixedB { get; set; }
    public double OneDouble { get; set; }
}       

关系是:

ComposedEntity 可能有 0 或 1 个 FixedEntityA

ComposedEntity 可能有 0 或 1 个 FixedEntityB

对id的约束是:

FixedEntityA 的 Id 是指向 ComposedEntity 的 Id 的 FK

FixedEntityB 的 Id 是指向 ComposedEntity 的 Id 的 FK

映射类为:

public ComposedEntity(): EntityTypeConfiguration<ComposedEntity>
{
    HasOptional(fea => fea.FixedA).WithRequired();
    HasOptional(feb => feb.FixedB).WithRequired();
}

这是我的 SaveChanges 覆盖:

foreach (var entry in ChangeTracker.Entries<IEntity>().Where(e => e.State == EntityState.Added))
{
   Type t = entry.Entity.GetType();

   List<DatabaseGeneratedAttribute> info = t.GetProperty("Id")
                                            .GetCustomAttributes(typeof (DatabaseGeneratedAttribute), true)
                                            .Cast<DatabaseGeneratedAttribute>().ToList();

   if (!info.Any() || info.Single().DatabaseGeneratedOption != DatabaseGeneratedOption.Identity)
   {
       if (entry.Entity.Id == Guid.Empty)
            entry.Entity.Id = (Guid) _idGenerator.Generate();
   }
}
return base.SaveChanges();

此代码适用于所有类型的关系,除了在这种情况下,我错过了一个测试,以确保我没有在作为外键的 id 上设置 id,而且我不知道如何检查是否Id 是 FK...

以下是此代码失败的示例对象:

var fea = new FixedEntityA();
var feb = new FixedEntityB();
var composedEntity = new ComposedEntity();

composedEntity.FixedA = fea;
composedEntity.FixedB = feb;

如果插入整个图表,所有三个对象都标记为已添加,并且所有 Id 都是默认值。

问题是,使用当前的 SaveChanges 方法,我将遍历更改跟踪器中具有已添加状态的所有对象,我将为所有具有默认 Guid 的实体分配一个 Id 并打破我的 FK 约束。

提前谢谢大家!

【问题讨论】:

  • 如果 Id 是 FK 不是 entry.Entity.Id != Guid.Empty 在这种情况下您不分配生成的 Id?我不太明白这个问题。对我来说,一个示例显示您的代码何时导致错误(以及哪些错误)会有所帮助。
  • @Slauma,我更新了消息,FixedEntityA & B 中的 ID 仍然为空,因为 DynamicProxy 已禁用
  • 我每次在 ComposedEntity 上设置 Id 时都尝试调用 DetectChanges,但它不会更新 FixedA 和 FixedB 上的 Id。

标签: entity-framework ef-code-first entity-framework-5


【解决方案1】:

这里有一些代码可以获取给定类型的 FK 属性(我知道这很可怕)。应该很简单,可以将其插入您的代码中。

var typeName = "Category";

var fkProperties = ((IObjectContextAdapter)db)
    .ObjectContext
    .MetadataWorkspace
    .GetItems<AssociationType>(DataSpace.CSpace)
    .Where(a => a.IsForeignKey)
    .Select(a => a.ReferentialConstraints.Single())
    .Where(c => c.FromRole.GetEntityType().Name == typeName)
    .SelectMany(c => c.FromProperties)
    .Select(p => p.Name);

【讨论】:

  • 谢谢罗文,去看看!
猜你喜欢
  • 2013-12-22
  • 2020-08-16
  • 2017-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多