Рассмотрим следующий сценарий:
public abstract class Entity
{
public object Id { get; set; }
}
public abstract class Entity<T> : Entity
{
public new T Id { get; set; }
}
public class Foo : Entity<Guid>
{
}
Если у меня есть следующий код:
var foo = new Foo { Id = Guid.NewGuid() };
db.Foos.Add(foo);
db.SaveChanges();
Я получаю исключение DbEntityValidation
говорящее, что Id
не разрешено иметь значение null. Если я отлаживаю, я вижу, что Foo.Id
действительно имеет значение, но если я Foo.Id
в базовый объект до уровня Entity
, Id
будет там null, и, похоже, это то, что Entity Framework использует для проверки а не без тени. Я чувствую, что у меня отсутствует что-то действительно основное; может быть, я просто не имел достаточно кофе сегодня утром. Любые идеи, что может быть проблемой?
Проблема в том, что
public new T Id { get; set; }
... в Entity<T>
скрывает свойство Id в Entity. Если вы это сделаете:
var foo = new Foo { Id = Guid.NewGuid() };
Entity entity = foo as Entity;
Console.WriteLine(entity.Id);
... что не собирается возвращать Guid, он будет возвращать то, что осталось за Entity.Id, который является объектом, который не был установлен.
Редактировать:
Крис придумал это, что должно хорошо работать.
public abstract class Entity<T> : Entity
{
public new T Id
{
get { return (T)base.Id; }
set { base.Id = value; }
}
}
Да, я пропустил что-то простое: Entity Framework некомпетентен и не поддерживает свойство shadowing. Я думал, что это произошло, потому что в прошлом я успешно использовал теневое копирование для изменения атрибутов свойств (например, сделать свойство, требуемое только в подклассе), но я никогда не зашел так далеко, чтобы фактически попытаться изменить тип.
ОБНОВИТЬ
Мне пришло в голову, что если бы я просто установил базовое свойство с правильным значением, все было бы хорошо. Итак, я изменил класс Entity<T>
на следующее:
public abstract class Entity<T> : Entity
{
public new T Id
{
get { return (T)base.Id; }
set { base.Id = value; }
}
}
Исключение ушло, и объект был успешно сохранен в базе данных. Есть ли какие-то непредвиденные последствия для этого, что мне не хватает?
var foo = new Foo(); foo.Id = Guid.NewGuid(); db.Foos.Add(foo); db.SaveChanges();