Ответ 1
Это ограничение. Ключевыми элементами могут быть только скалярные свойства непосредственно в сущности. Сложный тип представлен как комплексное свойство, которое не поддерживается.
В настоящее время я пытаюсь реализовать репозитории для своих объектов домена с помощью RC Entity Framework 4.1 и его первого подхода к коду. Теперь у меня есть объект домена "Voyage", который имеет уникальный идентификатор, инкапсулированный в типе "VoyageNumber"
public class VoyageNumber
{
private readonly string number;
public VoyageNumber(string number)
{
Validate.NotNull(number, "VoyageNumber is required");
this.number = number;
}
public string Id
{
get { return number; }
}
Теперь я получаю исключение, когда я делаю это в конфигурации моего DbContext:
modelBuilder.Entity<Voyage>().HasKey<VoyageNumber>(k => k.VoyageNumber);
Свойство 'VoyageNumber' не может быть используется как ключевое свойство для объекта "Domain.Model.Voyages.Voyage", потому что тип свойства не является допустимым ключом тип. Только скалярные типы, строки и byte [] - поддерживаемые типы ключей.
а также при попытке:
modelBuilder.Entity<Voyage>().HasKey<string>(k => k.VoyageNumber.Id);
Выражение свойств 'k = > k.VoyageNumber.Id 'недействителен. выражение должно представлять собой свойство: С#: 't = > t.MyProperty'
Неужели мне нужно уничтожить мой VoyageNumber и заменить его примитивным типом?
Это ограничение. Ключевыми элементами могут быть только скалярные свойства непосредственно в сущности. Сложный тип представлен как комплексное свойство, которое не поддерживается.
Для изолированного класса вы можете сделать обходной путь только для чтения, добавив метод "get" к вашему DbContext, который выполняет SqlQuery<>
, и отображает таблицу внутри класса (старомодно).
Я разработал минимальный тестовый сценарий здесь: https://github.com/timabell/ef-complex-pk
например.
public class TestDbContext : DbContext
{
public IEnumerable<UberWidget> GetUberWidgets()
{
return Database.SqlQuery<WidgetSqlDto>("select WidgetId, Name from Widgets")
.Select(dto => new UberWidget
{
UberWidgetId = new IdWrap { IdWrapId = dto.WidgetId },
Name = dto.Name
});
}
}
Мы можем решить это с помощью ниже. Надеюсь, это полезно.
public class TestPaperResultId: ValueObject
{
public TestPaperResultId(string testPaperId, string userId)
{
TestPaperId = testPaperId;
UserId = userId;
}
protected TestPaperResultId() { }
public string TestPaperId { get; protected set; }
public string UserId { get; protected set; }
public override string ToString()
{
return $"{TestPaperId}_{UserId}";
}
}
public class TestPaperResult : AggregateRoot
{
private TestPaperResultId _id;
public TestPaperResultId Id
{
get => _id ?? (_id = new TestPaperResultId(TestPaperId, UserId));
protected set
{
TestPaperId = value.TestPaperId;
UserId = value.UserId;
_id = value;
}
}
public string TestPaperId { get; protected set; }
public string UserId { get; protected set; }
protected TestPaperResult() { }
public TestPaperResult(TestPaperResultId id,
decimal fullmarks)
{
Id = id;
Fullmarks = fullmarks;
}
}
в dbContext:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<TestPaperResult>()
.Ignore(t => t.Id)
.HasKey(t => new {t.TestPaperId, t.UserId});
}
в репозитории:
public Task<TestPaperResult> FindTestPaperResultAsync(TestPaperResultId id)
{
return GetByKeyAsync<TestPaperResult>(id.TestPaperId, id.UserId);
}