Reputation: 1214
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
:-
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;
}
}
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
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
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
Reputation: 1
You can use a standard identifier for the database. GUID? stored as a field in the table.
Upvotes: -1