Попытка заполнить очень похожие отношения с помощью одного и того же свойства.C#

Место общения программистов C#
Ответить
Anonymous
 Попытка заполнить очень похожие отношения с помощью одного и того же свойства.

Сообщение Anonymous »

Я пытаюсь определить два класса с одним и тем же отношением коллекции, с помощью одного и того же ключа в третьем классе, предпочтительно с использованием аннотаций кода EF 6.
У меня есть три таблицы;
  • — это краткий справочник. Он содержит только последнюю версию каждого объекта, а не все поля. Он привязан к ObjectId (но также имеет VersionId, который увеличивается при каждом сохранении объекта)
  • — это история текущего. Он имеет точно такие же поля, что и Current, но здесь в ключ включен VersionId. Таким образом, он привязан к ObjectId + VersionId
  • содержит большой двоичный объект XML с полевыми изменениями объектов. Он содержит полный список полей, измененных между двумя версиями объекта, которые хранятся как «имя поля», «старое значение», «новое значение».

    У него есть столбец ObjectId, но вам необходимо проанализировать XML, чтобы получить задействованные значения VersionId (находятся в форме «старое значение», «новое значение»)
Как в текущих, так и в архивных классах мне нужна коллекция Changes с изменениями, связанными с этим ObjectId. Также было бы неплохо иметь обратные связи с Текущим и Архивом.
В терминах SQL код для заполнения каждого из этих отношений будет выглядеть так:

Код: Выделить всё

'Current.Changes' => SELECT * FROM Change WHERE ObjectId = 
'Archive.Changes' => SELECT * FROM Change WHERE ObjectId = 
'Change.Current' => SELECT * FROM Current WHERE ObjectId = 
'Change.ArchivedObjects' => SELECT * FROM Archive WHERE ObjectId = 
Вот как это выглядит сейчас:

Код: Выделить всё

[Table(nameof(Current))]
public class Current : ITrObject // = common interface for 'Current' and 'Archive'
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ObjectId { get; set; }
public int VersionId { get; set; }

// ... Lots of properties ...

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection Changes { get; set; }

}

[Table(nameof(Archive))]
public class Archive : ITrObject
{
[Key, Column(Order = 0), DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ObjectId { get; set; }
[Key, Column(Order = 1), DatabaseGenerated(DatabaseGeneratedOption.None)]
public int VersionId { get; set; }

// ... Lots of properties ...

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection Changes { get; set; }
}

[Table(nameof(Change))]
public class Change
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ChangeId { get; set; }

public int? ObjectId { get; set; }  // 'int?' because the source system sometimes creates changes that are logged, but not saved yet. Probably some kind of 'autosave' feature.

// ...  Lots of properties ...

[ForeignKey(nameof(ObjectId))]
public virtual Current Current { get; set; }

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection ArchivedObjects { get; set; }
}
Код построителя моделей:

Код: Выделить всё

modelBuilder.Entity()
.HasMany(cur => cur.Changes)
.WithOptional(chg => chg.Current)
.HasForeignKey(chg => chg.ObjectId)
.WillCascadeOnDelete(false);

modelBuilder.Entity()
.HasMany(arch => arch.Changes)
.WithMany(); // Stuck here...
(Весь код был сокращен и несколько анонимизирован, но я надеюсь, что теперь я уловил все опечатки.)
Возможно ли это вообще в EF 6? Если нет, есть ли у вас какие-либо предложения о том, как сделать это каким-либо другим способом, который не будет полностью портить остальную часть извлечения данных EF 6?
Отношения на самом деле не такие уж сумасшедшие, поэтому было бы неплохо, если бы это можно было сделать.
Я имею некоторое влияние на базу данных, но в основном оно предоставлено.
Я имею гораздо больше влияния на нее код C#, но и там я не могу делать слишком сумасшедшие вещи - например, переход на другой ORM...
РЕДАКТИРОВАТЬ: некоторые из конфигураций, которые я пробовал, и их ошибки SQL

Код: Выделить всё

modelBuilder.Entity()
.HasMany(arch => arch.Changes)
.WithMany();
... выдает ошибку SqlException: неверное имя объекта «Change_ChangeId».

Код: Выделить всё

modelBuilder.Entity()
.HasMany(arch => arch.Changes)
.WithMany(chg => chg.Archive);
... выдает ошибку SqlException: неверное имя объекта 'dbo.ArchiveChanges'.

Код: Выделить всё

modelBuilder.Entity()
.HasMany(chg => chg.ArchivedObjects)
.WithMany();
... выдает ошибку SqlException: Недопустимое имя столбца «Archive_ObjectId». Недопустимое имя столбца «Archive_VersionId». Недопустимое имя столбца «Archive_ObjecId».... повторяется до тех пор, пока не будет усечено.

Код: Выделить всё

modelBuilder.Entity()
.HasMany(chg => chg.ArchivedObjects)
.WithMany(arch => arch.Changes);
... выдает ошибку SqlException: неверное имя объекта "dbo.ChangeArchivedObjects"..


Подробнее здесь: https://stackoverflow.com/questions/797 ... e-property
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»