Anchit Pancholi
Anchit Pancholi

Reputation: 1214

Entity Framework with Nullable Guid? causing Validation Error

I am trying to use Nullable Guid in Entity Framework but when i tried to commit the change i am getting validation message due to foreign key is null, I have below domain class, DomainType Class has child DomainCustomField :-

DomainType.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;
        }
    }
}

DomainCustomField.cs

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

below is mapping :-

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);

below is sample code which i tried to insert.

 DomainType domainType = new DomainType()
        {
            AccountId = customer.Id
        };
        domainType.DomainCustomFields.Add(new DomainCustomField()
        {
            Name = "Test"
        });
        Workspace.Add<DomainType>(domainType);
        Workspace.CommitChanges();

Error :- validation error for DomainTypeId is required

in the same code if i change Guid? to Guid in ID variable then its work correctly. I don't know how to handle nullable Guid. do i need to manually set parent key in child reference? then how it works fine in case of Guid?

Note :- I am using using Guid because i am working with distributed database, where id can generate from multiple source system. I am using Guid? because by default Guid generate 00000000-0000-0000-0000-000000000000 for empty Guid which can grow database size.

Upvotes: 0

Views: 9664

Answers (3)

Heberda
Heberda

Reputation: 820

I'll take a slightly different approach in my answer and try and tell you what to change in order to get a working example;

Like someone has pointed out, unique identifiers must not be nullable so the Id field in DomainType should a Guid. Also you will need to change the Id field in DomainCustomField. These may need an empty constructor just to create a new Guid.

Secondly, the foreign key in your other object Guid? DomainTypeId is perfectly fine, this can stay, but if it is staying you will need to change your configuration.

In this block you have specified that the property is required?

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

So simply make it optional;

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

That should solve your issues. Any questions let me know :)

Upvotes: 1

Ivan Stoev
Ivan Stoev

Reputation: 205629

The issue has nothing to do with Guid type (the same will happen with int), but the discrepancy between the nullability of the property type used in the entity and the actual nullability of the property implied by the model.

First, EF requires PKs to be non nullable. Hence DomainType.Id, DomainCustomField.Id and DomainCustomField.DomainTypeId are effectively non nulable (it's unclear why you have include DomainTypeId in the PK of the DomainCustomField which already have unique database generated Id, but that's another story).

Second, DomainCustomField.DomainTypeId is effectively non nullable because you have specified that - the WithRequired() part of the FK relationship configuration.

Now, EF does its best to handle these discrepancies. If you look at the generated migration, you will see that the corresponding database table columns of all the fields in question are non nullable. However (nothing is perfect, you know) some part of the EF code is failing to handle that discrepancy and hence the exception.

With that being said, always keep the model properties nullability in sync with their actual nullability. Which in you case is to make both 3 properties non nullable (i.e. of type Guid).

P.S. What about the note I am using Guid? because by default Guid generate 00000000-0000-0000-0000-000000000000 for empty Guid which can grow database size., I have no idea what do you mean by that. The nullablitity of the class property has nothing to do with the database size, and as I already mentioned, the corresponding database table columns for such setup are non nullable anyway.

Also note that in your example you forget to set the Id of the new DomainType, which you should because it's not auto generated.

Upvotes: 2

npsavin
npsavin

Reputation: 1

You can use a standard identifier for the database. GUID? stored as a field in the table.

Upvotes: -1

Related Questions