LINQ to SQL: Как настроить связи между двумя таблицами, чтобы заполнить список строк - PullRequest
0 голосов
/ 24 апреля 2011

У меня есть простая база данных с двумя таблицами: Photo и Tag.Между двумя таблицами существует отношение один ко многим (фотография может иметь много тегов).Вот диаграмма:

Tables

Теперь я создал класс Photo и настроил его для LINQ-to-SQL с использованием атрибутов.Код этого класса приведен ниже:

[Table]
public class Photo
{

    [Column(IsDbGenerated = true, IsPrimaryKey = true, CanBeNull = false)]
    public int ID { get; set; }

    [Column(CanBeNull = false)]
    public string Filename { get; set; }

    [Column(CanBeNull = false)]
    public string Description { get; set; }

    [Column(CanBeNull = false)]
    public DateTime DateTaken { get; set; }


    public List<string> Tags { get; set; }

    public override string ToString()
    {
        string result = String.Format("File: {0}, Desc: {1}, Date: {2}, Tags: ", 
            Filename, Description, DateTaken);
        if (Tags != null)
            foreach (string tag in Tags)
                result += tag + ", ";
        return result;
    }
}

Вы заметите, что в настоящее время у меня нет атрибутов для списка Tags.Я хотел бы иметь возможность настроить атрибуты (ассоциации) для списка Tags, чтобы он был заполнен полем Name таблицы Tag для всех записей в таблице Tag конкретного PhotoID.Было бы предпочтительнее, если бы я мог сделать это напрямую (т.е. без необходимости настраивать класс Tag, имитирующий / относящийся к таблице Tag).Поскольку меня интересует только одно поле (имя в таблице тегов), а не много полей, я думаю, что есть способ сделать это.

Возможно ли это, и если да, то как мне дальшеукрасить класс атрибутами и каков будет синтаксис для простого запроса на выбор с использованием LINQ-to-SQL?

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

DataContext context = new DataContext(connectionString);

// add new photo
Photo newPhoto = new Photo { Filename = "MyImage1.jpg", Description = "Me", DateTaken = DateTime.Now };
context.GetTable<Photo>().InsertOnSubmit(newPhoto);
context.SubmitChanges();

// print out all photos
var photoQuery = from m in context.GetTable<Photo>() select m;
foreach (Photo myPhoto in photoQuery)
    textBox1.Text += Environment.NewLine + myPhoto.ToString();

Ответы [ 2 ]

1 голос
/ 24 апреля 2011

Сначала я бы предложил вам использовать инструмент для генерации ваших классов сущностей (классов, которые соответствуют таблицам базы данных). Мы используем sqlmetal, и он отлично справляется со своей работой.
Затем (если у вас есть объект Tag), чем написать функцию, которая выбирает теги для некоторых фотографий:

void GetTags(IEnumerable<Photo> photos)
{
var ids = photos.Select(p=>p.ID).ToList();
var tagsG = (from tag in context.GetTable<Tag>() where ids.Contains(tag.PhotoID) select new {PhotoID, Name}).GroupBy(tag=>tag.PhotoID);
foreach(ph in photos){
ph.Tags = tagsG[ph.ID].Select(tag=>tag.Name).ToList();
}
}

Обратите внимание, код может не скомпилироваться. Я написал его в браузере ...

1 голос
/ 24 апреля 2011

Вы должны обратиться к статье Отображение на основе атрибутов в msdn.

Кроме того, в этой статье показано, как украсить свойство EntitySet с атрибутом Association для выполнения моделирования отношений.

Было бы предпочтительно, если бы я мог сделать это напрямую (т.е. без необходимости настраивать класс Tag, имитирующий / относящийся к таблице Tag).

Не возможно. LinqToSql должен знать, что такое таблица или нет, чтобы он мог генерировать правильный текст SQL.

Вместо этого вы можете создать один набор типов для представления структуры базы данных и другой набор типов для использования в других местах вашей программы. Второй набор типов может иметь один класс, представляющий данные Photo и Tag.

Напишите запрос с первым набором типов, а затем используйте их для создания экземпляров второго набора.

...