2015-07-20 2 views
2

Я использую EF для хранения данных в базе данных SQL Server.Хранение коллекции с несколькими одинаковыми элементами

Есть 2 типа данных:

  1. Image
  2. Символ

Каждый символ содержит коллекцию изображений

public virtual ICollection<Image> Images { get; set; } 

и каждое изображение содержит набор символов :

public virtual ICollection<Symbol> Symbols { get; set; } 

EF создает таблицу отношений для отношений «многие-ко-многим».

Если новый символ создан (загружен), программа просматривает таблицу изображений, если эти изображения уже загружены.

Если да, то будет добавлен в список изображений нового символа.

Теперь есть символ с 3 изображениями (все равно!), И он будет добавлен в таблицу Symbols.

Но в таблице отношений создается ТОЛЬКО ОДИН элемент !?

Так что в следующий раз, когда это Symbol считывается из базы данных он просто содержит только 1 изображение ...

Что я делаю неправильно?

Или что было бы правильным путем?

Таблица структуры:

[Table("Images")] 
public class SqlSymbolImgInfo 
{ 
    [Key] 
    public int Id { get; set; } 

    public String Path { get; set; } 
    public long Size { get; set; } 
    public String Md5 { get; set; } 
    public int X { get; set; } 
    public int Y { get; set; } 

    public virtual ICollection<SqlSymbol> Symbols { get; set; } 

    public override int GetHashCode() 
    { 
     return System.IO.Path.GetExtension(Path ?? "x.png").GetHashCode() + Size.GetHashCode() + (Md5 ?? "").GetHashCode(); 
    } 
} 

[Table("Symbols")] 
public class SqlSymbol 
{ 
    [Key] 
    public int Id { get; set; } 

    public String Description { get; set; } 
    public int Type { get; set; } 

    public virtual ICollection<SqlSymbolImgInfo> Images { get; set; } 
} 

enter image description here

Создание отношения:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>(); 

     modelBuilder.Entity<SqlSymbol>().HasMany(s => s.Images).WithMany(i => i.Symbols); 

     base.OnModelCreating(modelBuilder); 
    } 

Добавление символов:

  1. Добавьте изображения, если они п ВЗ существует

  2. Получить добавленные изображения назад

  3. Добавить символ

    public void AddSymbol(Symbol sym) 
    { 
        try 
        { 
         using (var db = new Db()) 
         { 
          // check if images already exists or add them.. 
          foreach (var img in sym.Images) 
          { 
           var exImg = db.FindImage(img); 
           if (exImg == null) 
           { 
            var newImg = db.Images.Add(img.ConvertToSqlSymbolImgInfo()); 
            db.SaveChanges(); 
            img.Id = newImg.Id; // get Id of new image 
           } 
           else 
           { 
            img.Id = exImg.Id; // get Id of existing image 
           } 
          } 
    
          var sqlSym = sym.ConvertToSqlSymbol(); 
          // get the existing entries, otherwise the same image will be added again and again... 
          sqlSym.Images = sym.Images.Select(i => db.Images.Find(i.Id)).ToList(); 
    
          db.Symbols.Add(sqlSym); 
          db.SaveChanges(); 
          sym.Id = sqlSym; 
         } 
        } 
        catch { logIt("error while adding a symbol."); } 
    } 
    

Для объяснения:

Мне нужно использовать классы-оболочку для рамочной сущности тяжбы Symbol и Image классы находятся в общей библиотеке. И я не хочу включать EF во все другие проекты, даже если я его не использую.

Некоторые ДОПОЛНИТЕЛЬНО:

Символ 3 одинаковых изображений:

enter image description here

Коллекция после добавления и "поиск" изображение:

enter image description here

После добавления этого Symbol в базу данных, посмотрите на таблицы:

Images стол:

enter image description here

и таблица отношений:

enter image description here

!! отмеченная строка должна быть там 3 раза?!

Его Symbol с идентификатором 50, который имеет 3 Images с идентификатором 108. Не только один!

Вот упрощенный проект, чтобы проверить это с помощью всего нескольких строк кода:

test project

+0

Что не так, если у вас есть * одно изображение в базе и несколько копий этого изображения в памяти (при условии, что вы действительно хотите по какой-то причине)? – Tigran

+0

еще несколько деталей: в «Картинке-таблице» представлены все доступные изображения. И у Символов есть только «ссылки» на содержащиеся Изображения .. Так что если есть Символ с несколькими кратными тем же изображением, я не могу его сохранить в данный момент. – mxii

+0

Не могли бы вы показать нам структуру таблиц ** - большинство важная таблица, содержащая многозначное сопоставление между символами и изображениями. –

ответ

1

Как написал в своем комментарии, многие-ко-многим таблице отношение имеет ПК, определенная на оба ключа FK, поэтому невозможно добавить одну и ту же комбинацию дважды. Сначала я бы подумал, действительно ли такая ситуация действительно возможна в вашей бизнес-модели. Если это так, то один из способов, которым вы можете пойти, вручную объявляет вашу промежуточную таблицу и дает ей искусственный ПК (например, только автоинкрементный int).

Тогда в EF у вас будет два отношения один-ко-многим (от Symbol и от Image до промежуточной таблицы, которую вы можете назвать любым - например, ImagesInSymbol или около того). Использование этих коллекций будет менее удобным, но будет работать. И в качестве бонуса вы сможете позже установить другие свойства этого отношения (например, DateCreated, Status и т. Д.).

Подробнее см. Здесь question.

+1

То, как я сейчас работаю. Я думал, что в EF должен быть какой-то способ, но, к сожалению, мне нужно сделать это вручную. Для более подробной информации, как это сделать, см. Ссылку ниже вашего ответа. – mxii

Смежные вопросы