Легкая загрузка таблицы данных MVVM из двух таблиц реляционной базы данных - PullRequest
0 голосов
/ 19 июля 2010

Как загрузить DataGrid с двумя связанными таблицами, используя MVVM light, я использую .NET RIA и silverlight 4.

например, если мои таблицы данных:

userInfo- ИД пользователя, Имя, АДРЕС
Адрес - AddressID, StreetName, Zip

как мне создать сетку данных, которая отображает [Name, StreetName, ZIp]

Ответы [ 2 ]

1 голос
/ 28 февраля 2012

Прежде всего вы должны включить адресную таблицу в GetQuery для UserInfo в ваш класс DomainService, как показано ниже ...

  [Query]
  public IQueryable<UserInfo> GetUserInfos()
    {
        return this.ObjectContext.UserInfos.Include("Address");
    }

затем в файле метаданных вы должны добавить [Включить] чуть выше

  [Include]
        public Addresses Address{ get; set; }
        public int AddressID { get; set; }

Теперь создайте решение. Теперь в Xaml вы можете использовать вот так

  <sdk:DataGrid ItemsSource="{Binding UserList, Mode=TwoWay}" SelectedItem="{Binding CurrentUser, Mode=TwoWay}" Margin="0,0,0,2" AutoGenerateColumns="False">
        <sdk:DataGrid.Columns>
            <sdk:DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/>
            <sdk:DataGridTextColumn Header="Street Name" Binding="{Binding Path=Address.StreetName}"/>
            <sdk:DataGridTextColumn Header="Zip" Binding="{Binding Path=Address.Zip}"/>
        </sdk:DataGrid.Columns>

    </sdk:DataGrid>
0 голосов
/ 20 июля 2010

Здесь возможна пара подходов. Я объясню оба, которые приходят на ум. Во-первых, используется отношение, уже определенное в вашей базе данных. Второе - возврат через пользовательский класс модели.

Вариант 1: Я предполагаю, что вы создали Entity Framework Model (со связью) из своей базы данных в веб-проекте и создали DomainService для размещения этой модели. !!! Один ключ, который нужно сделать при создании модели, - это создать классы метаданных для моделей !!! (Я пропустил это первые несколько раз, и очень важно изменить поведение ваших моделей, например, здесь)

В модели метаданных вы найдете свойство ассоциации и украсите его атрибутом [Include]. Вот пример из другого проекта с WorklanDetail, где я хочу вернуть связанные Назначения:

[MetadataTypeAttribute(typeof(WorkplanDetailMetadata))]
public partial class WorkplanDetail
{
    internal sealed class WorkplanDetailMetadata
    {
        [Include]
        public EntityCollection<Assignment> Assignments { get; set; }
    }
}

затем, вы можете просто сослаться на свойство в приложении Silverlight, и альта ваши данные адреса доступны.

Чтобы связать одну сущность (EntityReference, а не коллекцию), вы просто будете использовать свое свойство для доступа к под-сущности в привязке вашей таблицы данных ... Например:

Text="{Binding Path=Address.StreetName}"

Это самый простой из известных мне методов.

Вариант 2 требует создания собственного пользовательского класса (по крайней мере, вы должны иметь свойство, украшенное атрибутом [Key], чтобы облегчить передачу в / из клиента). Вот пример, который я использовал для получения информации о результатах поиска в папке:

public class FolderSearchResult
{
    [Key]
    public string EFOLDERID { get; set; }
    public string Subject { get; set; }
    public string FolderName { get; set; }
}

Ключ в том, что у свойства EFOLDERID есть атрибут [Key], который уникальным образом идентифицирует каждый элемент как PK в базе данных.

Тогда в вашем классе обслуживания вы можете вернуть такой вид:

public IEnumerable<FolderSearchResult> GetFolderResults(string search)
    {
        var query = from ge in this.ObjectContext.Generic_Engagement
                    from f in this.ObjectContext.eFolders
                    where ge.EFOLDERID == f.eFolderID &
                    f.eArchived == 0 &
                    f.eSubject.Contains(search) &

                    (from wp in this.ObjectContext.Workplans
                     where wp.EFOLDERID == f.eFolderID
                     select wp).Count() == 0 &

                     (from r in this.ObjectContext.Resources
                      where r.EFOLDERID == f.eFolderID
                      select r).Count() == 0

                    select new FolderSearchResult()
                      {
                        EFOLDERID = f.eFolderID,
                        FolderName = f.eFolderName,
                        Subject = f.eSubject
                      };
        return query.AsEnumerable<FolderSearchResult>();
    }

Пара замечаний об этом подходе:

  1. На мой взгляд, это работает лучше всего, когда вам не нужен доступ только для чтения. Если вы делаете обновления / вставки / удаления, используйте первый подход.
  2. Это хорошо помогает, когда вам нужно создать какой-то логический объект между совершенно разными источниками данных (например, идентификатор пользователя и идентификатор сотрудника из базы данных, а также отображаемое имя, местоположение сайта и т. Д. Из Active Directory).
  3. Обновление таким способом возможно, но вы должны проделать немного больше работы, чтобы отделить ваши элементы и правильно обновить все.

Таким образом, я бы предложил использовать первый подход, если только не происходит следующее: вам нужен логический объект, который пересекает хранилище данных (отдельные источники БД), или вам нужен быстрый доступ только для чтения (такой как привязка ItemSource для отбрасывания) список).

Выгрузка логики сортировки и фильтрации на сервер, даже за счет дополнительных объектов, загруженных в память, чтобы ваш клиент мог оставаться быстрым, приносит мне пользу. Использование локальной сортировки в CollectionViewSource или чего-то подобного может сделать то же самое, но только некоторые из них могут начать замедлять скорость вашего приложения.

...