2

Я создаю приложения с помощью C#/нетто 4,5 и EF 6 и было интересно, если я мог бы сделать следующее как-то:.Повторное использование унаследованных FK-отношений?

У меня есть две базовые классы, как:

public class BaseItem 
{ 
    [Key] 
    public int Id { get; set; } 

    public List<BaseRevision> Revisions { get; set; } 
} 

public class BaseRevision 
{ 
    [Key] 
    public int Id { get; set; } 

    public BaseItem Item { get; set; } 
} 

Теперь я получить оба им так:

[Table("ContentItems")] 
public class ContentItem : BaseItem 
{ 
    public string ContentType { get; set; } 
} 

[Table("ContentRevisions")] 
public class ContentRevision : BaseRevision 
{ 
    public string Text { get; set; } 
} 

Это прекрасно работает и EF даже обрабатывает запросы, как:

var revisions = db.ContentItems.Where(i => i.Revisions.Any(r => (r as ContentRevision).Text.Contians("ABC"))); 

Это преобразование в SQL, как и следовало ожидать, но я хотел бы «избавиться, если as» (это вызывает гораздо большее осложнение в некоторых других случаях).

Я попытался использовать генерики BaseItem, но это не поддерживается EF, так что я попытался следующие:

[Table("ContentItems")] 
public class ContentItem : BaseItem 
{ 
    public string ContentType { get; set; } 

    public List<ContentRevision> ContentRevisions { get; set; } 
} 

[Table("ContentRevisions")] 
public class ContentRevision : BaseRevision 
{ 
    public string Text { get; set; } 

    public ContentItem ContentItem { get; set; } 
} 

Так что я мог бы использовать приведенный выше запрос, как:

var revisions = db.ContentItems.Where(i => i.ContentRevisions.Any(r => r.Text.Contians("ABC"))); 

Но я могу 'заставить его работать, используя унаследованный внешний ключ "Item_Id" в таблице "BaseItems". EF всегда хочет создать второе FK-Relation, используя новый ключ «ContentItem_Id» в таблице «ContentItems», который будет дублировать отношение (и, возможно, вызвать некоторые другие побочные эффекты).

Возможно ли это (или у кого-то есть лучшая идея решить/улучшить эту проблему/образец)?

ОБНОВЛЕНИЕ: демонстрационный проект можно скачать HERE. Если вы добавите новую миграцию, это создаст второе FK-сопоставление, которое я не хочу ...

+0

ARE есть таблицы для BaseItem и BaseRevision в базе данных (4 таблицы) или просто созданные ContentItem и ContentRevision (2 таблицы)? – acarlon

+0

Извините, если это очевидный вопрос, я просто хотел убедиться, что правильно понял. Это хороший вопрос. – acarlon

+0

@acarlon: из-за атрибута «Таблица» создано 4 таблицы, и я хочу, чтобы у меня было много классов, полученных из этой базы ... – ChrFin

ответ

1

EDIT:

Вам не нужно, чтобы добавить сложные отношения здесь , это именно то, для чего предназначен OfType <>.

Если вы хотите получить доступ только к своим ContentItems, insteed создания нового списка в вашем inheriteded объекта используется список BaseItem и написать:

(i is a BaseItem) 
i.Revison.OfType<ContentItem> 

Вы будете использовать этот общий список для хранения всех ваших differents BaseItems. Благодаря компилятору, он не содержит ошибок, потому что при использовании функции OfType <> func вы получите только типизированные объекты.

Initial Ответ: Если первоначальная проблема заключается в том, что все вы пересмотров не ContentRevision и что это может вызвать ваш запрос потерпеть неудачу на as преобразования, вы должны написать так:

var revisions = db.ContentItems.Where(i => i.Revisions.OfType<ContentRevision>.Any(r => r.Text.Contains("ABC"))); 
+0

Нет, 'как' отлично работает, я просто не хочу этого, потому что на самом деле это не« сохранить », поскольку вы также можете использовать неверный тип ... – ChrFin

+0

Вы хотите иметь Список Изменения в вашем базовом элементе и список в вашем ContentItem. Здесь вам не нужно добавлять сложное отношение, это именно то, для чего предназначен OfType <>. При написании i.ContentRevision для доступа к вашим CotentItems вы пишете i.Revison.OfType . У вас есть только один список из двух, вам не нужно их синхронизировать, вы можете добавить много разных базовых элементов в один список и только получить доступ к тем, которые вы хотите легко. Все они сохранены в db, и это безошибочно. Поскольку компилятор не позволит вам использовать неправильный тип. –

+0

Попробуйте, прежде чем покупать, вы не пожалеете;) –

0

Пробовали ли вы использовать аннотации данных ForeignKey, чтобы указать структуру сущности, какие свойства использовать для внешнего ключа. То есть

public class BaseItem 
{ 
    [Key] 
    public int Id { get; set; } 

    public List<BaseRevision> Revisions { get; set; } 
} 

public class BaseRevision 
{ 
    [Key] 
    public int Id { get; set; } 

    [ForeignKey("Id")] 
    public BaseItem Item { get; set; } 
} 

[Table("ContentItems")] 
public class ContentItem : BaseItem 
{ 
    public string ContentType { get; set; } 
} 

[Table("ContentRevisions")] 
public class ContentRevision : BaseRevision 
{ 
    public string Text { get; set; } 
} 

или с помощью Fluent API для определения ИЭ отношения для класса BaseItem

modelBuilder.Entity<BaseItem>() 
.HasMany(t => t.Revisions) 
.WithRequired(t => t.Item) 
.HasForeignKey(t => t.Id); 
+0

Я попробовал это, используя аннотацию данных, но не с помощью свободного API. Попробуем это и отчитаемся ... – ChrFin

+0

UPDATE: Также не работает с текущим API ... – ChrFin

0
public class BaseItem 
{ 
    [Key] 
    public int Id { get; set; } 

    public List<BaseRevision> Revisions { get; set; } 
    } 

public class BaseRevision 
{ 
    [Key] 
    public int Id { get; set; } 

    public Int BaseItemID{get;set;} 
    [ForeignKey("BaseItemID")] 
    public BaseItem Item { get; set; } 
    } 
+0

Лучше, поскольку он не создает отдельный столбец сопоставления, но все же создает новый FK (и недопустимый индекс). – ChrFin