具有Nullable Guid的实体框架?导致验证错误

时间:2017-02-17 04:22:09

标签: c# entity-framework entity-framework-6

我正在尝试在实体框架中使用Nullable Guid但是当我尝试提交更改时,由于外键为null,我得到验证消息,我在域类下面{{1类具有子DomainType: -

DomainType.cs

DomainCustomField

DomainCustomField.cs

public class DomainType
{
    public Guid? Id
    {
        get;
        set;
    }
    private IList<DomainCustomField> _domainCustomFields;

    public string Name
    {
        get;
        set;
    }

    public Guid? AccountId
    {
        get;
        set;
    }

    public virtual IList<DomainCustomField> DomainCustomFields
    {
        get
        {
            return this._domainCustomFields;
        }
        set
        {
            this._domainCustomFields = value;
        }
    }
}

下面是映射: -

public class DomainCustomField 
{
        public Guid? Id
        {
                get;
                set;
        }
        public string Name
        {
            get;
            set;
        }
        public Guid? DomainTypeId
        {
            get;
            set;
        }
}
下面的

是我试图插入的示例代码。

modelBuilder.Domain<DomainCustomField>().HasKey((DomainCustomField p) => new
            {
                p.Id,
                p.DomainTypeId
            });
            modelBuilder.Domain<DomainCustomField>()
                .Property(p => p.Id)
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            modelBuilder.Domain<DomainType>()
                .HasMany(p => p.DomainCustomFields)
                .WithRequired()
                .HasForeignKey<Guid?>(x => x.DomainTypeId);

错误: - 需要DomainTypeId的验证错误

在同一代码中,如果我在ID变量中将 DomainType domainType = new DomainType() { AccountId = customer.Id }; domainType.DomainCustomFields.Add(new DomainCustomField() { Name = "Test" }); Workspace.Add<DomainType>(domainType); Workspace.CommitChanges(); 更改为Guid?,那么它的工作正常。我不知道如何处理Guid nullable。我是否需要在子引用中手动设置父键?然后在Guid的情况下如何正常工作?

注意: - 我正在使用Guid,因为我正在使用分布式数据库,其中id可以从多个源系统生成。 我正在使用Guid,因为默认情况下Guid?会为空Guid生成00000000-0000-0000-0000-000000000000,这会增加数据库大小。

3 个答案:

答案 0 :(得分:1)

我会在答案中采取略微不同的方法,并试着告诉你要改变什么才能得到一个有效的例子;

就像有人指出的那样,唯一标识符不能为空,因此Id中的DomainType字段应为Guid。您还需要更改DomainCustomField中的Id字段。这些可能只需要一个空的构造函数来创建一个新的Guid。

其次,你的另一个对象Guid? DomainTypeId中的外键完全正常,这可以保留,但如果它停留,则需要更改配置。

在此块中,您已指定该属性是必需的吗?

modelBuilder.Domain<DomainType>()
                .HasMany(p => p.DomainCustomFields)
                .WithRequired()
                .HasForeignKey<Guid?>(x => x.DomainTypeId);

所以简单地将它设为可选;

modelBuilder.Domain<DomainType>()
                .HasMany(p => p.DomainCustomFields)
                .WithOptional()
                .HasForeignKey<Guid?>(x => x.DomainTypeId);

那应该可以解决你的问题。有任何问题让我知道:)

答案 1 :(得分:0)

该问题与Guid类型无关(int会发生同样的情况),但实体中使用的属性类型的可为空性与属性的实际可为空性之间存在差异模型暗示。

首先,EF要求PK不可为空。因此,DomainType.IdDomainCustomField.IdDomainCustomField.DomainTypeId实际上是不合法的(不清楚为什么你已经在DomainTypeId的PK中包含DomainCustomField有唯一的数据库生成Id,但这是另一个故事)。

其次,DomainCustomField.DomainTypeId实际上是不可为空的,因为您已指定 - FK关系配置的WithRequired()部分。

现在,EF尽力解决这些差异。如果查看生成的迁移,您将看到所有相关字段的相应数据库表列不可为空。然而(没有什么是完美的,你知道)EF代码的某些部分未能处理这种差异,因此也是例外。

话虽如此,始终将模型属性的可空性与其实际的可空性保持同步。在你的情况下,这三个属性都是不可为空的(即类型Guid)。

P.S。我正在使用Guid?的注释,因为默认情况下Guid为空00000000-0000-0000-0000-000000000000生成Guid,这可能会增加数据库大小。,我没有想法是什么意思。类属性的无可比性与数据库大小无关,正如我已经提到的,这种设置的相应数据库表列无论如何都是不可为空的。

另请注意,在您的示例中,您忘记设置新Id的{​​{1}},因为它不是自动生成的。

答案 2 :(得分:-1)

您可以使用数据库的标准标识符。 GUID?存储为表格中的字段。