Подтвердить что ты не робот

Рекомендации по использованию Entity Framework с WPF DataBinding

Я занимаюсь созданием своего первого реального приложения WPF (т.е. первого, предназначенного для использования кем-то, кроме меня), и я все еще обдумываю лучший способ сделать что-то в WPF. Это довольно простое приложение для доступа к данным, использующее еще довольно-таки новую Entity Framework, но мне не удалось найти много руководств в Интернете, чтобы наилучшим образом использовать эти две технологии (WPF и EF) вместе. Поэтому я подумал, что выброшу, как я подхожу к нему, и посмотрю, есть ли у кого-нибудь лучшие предложения.

  • Я использую Entity Framework с SQL Server 2008. EF поражает меня как намного сложнее, чем нужно, и еще не созрел, но Linq-to-SQL, по-видимому, мертв, поэтому я может также использовать технологию, на которую, как представляется, сосредоточена MS.

  • Это простое приложение, поэтому я (пока) не счел нужным создавать отдельный слой данных вокруг него. Когда я хочу получить данные, я использую довольно простые запросы Linq-to-Entity, обычно прямо из моего кода, например:

    var families = from family in entities.Family.Include("Person")
               orderby family.PrimaryLastName, family.Tag
               select family;
    
  • Запросы Linq-to-Entity возвращают результат IOrderedQueryable, который автоматически не отражает изменения в базовых данных, например, если я добавлю новую запись через код в модель данных сущности, наличие этого нового запись не будет автоматически отражена в различных элементах управления, ссылающихся на запрос Linq. Следовательно, я бросаю результаты этих запросов в ObservableCollection, чтобы фиксировать основные изменения данных:

    familyOC = new ObservableCollection<Family>(families.ToList());
    
  • Затем я сопоставляю ObservableCollection с CollectionViewSource, чтобы я мог получать фильтрацию, сортировку и т.д., не возвращаясь в базу данных.

    familyCVS.Source = familyOC;
    familyCVS.View.Filter = new Predicate<object>(ApplyFamilyFilter);
    familyCVS.View.SortDescriptions.Add(new System.ComponentModel.SortDescription("PrimaryLastName", System.ComponentModel.ListSortDirection.Ascending));
    familyCVS.View.SortDescriptions.Add(new System.ComponentModel.SortDescription("Tag", System.ComponentModel.ListSortDirection.Ascending));
    
  • Затем я связываю различные элементы управления и что-то не с этим CollectionViewSource:

    <ListBox DockPanel.Dock="Bottom" Margin="5,5,5,5" 
        Name="familyList" 
        ItemsSource="{Binding Source={StaticResource familyCVS}, Path=., Mode=TwoWay}" 
        IsSynchronizedWithCurrentItem="True" 
        ItemTemplate="{StaticResource familyTemplate}" 
        SelectionChanged="familyList_SelectionChanged" />
    
  • Когда мне нужно добавлять или удалять записи/объекты, я вручную делаю это как из модели данных сущности, так и из ObservableCollection:

    private void DeletePerson(Person person)
    {
        entities.DeleteObject(person);
        entities.SaveChanges();
        personOC.Remove(person);
    }
    
  • Обычно я использую элементы StackPanel и DockPanel для позиционирования элементов. Иногда я использую Grid, но мне сложно поддерживать: если вы хотите добавить новую строку в верхнюю часть сетки, вам нужно прикоснуться к каждому элементу управления, непосредственно размещенному в сетке, чтобы сообщить ему использовать новую строку. Uggh. (Microsoft никогда, казалось, не получала концепцию DRY.)

  • Я почти никогда не использую конструктор VS WPF для добавления, изменения или управления позициями. Дизайнер WPF, который поставляется с VS, несколько смутно полезен, чтобы увидеть, как будет выглядеть ваша форма, но даже тогда, ну, на самом деле, особенно если вы используете шаблоны данных, которые не привязаны к данным, доступным на время разработки. Если мне нужно отредактировать мой XAML, я беру его как человек и делаю это вручную.

  • Большая часть моего реального кода находится на С#, а не на XAML. Как я уже упоминал в другом месте, полностью исключая тот факт, что я еще не привык к "размышлению" в нем, XAML поражает меня как неуклюжий, уродливый язык, который также случается с плохой поддержкой дизайнера и intellisense, и это невозможно отладить. Uggh. Следовательно, всякий раз, когда я могу ясно видеть, как сделать что-то в коде С#, я не могу легко увидеть, как это сделать в XAML, я делаю это на С#, не извиняясь. Было много написано о том, как хорошая практика почти никогда не использовать код на странице WPF (скажем, для обработки событий), но по крайней мере, по крайней мере, это не имеет для меня никакого смысла. Почему я должен что-то делать с уродливым, неуклюжим языком с ужасным синтаксисом, ужасно плохим редактором и практически без безопасности типа, когда я могу использовать хороший, чистый язык, такой как С#, который имеет редактор мирового класса, почти идеально intellisense и безопасность беспрецедентного типа?

Итак, где я нахожусь. Какие-либо предложения? Я пропустил какие-то большие части этого? Что-нибудь, о чем я действительно должен думать по-другому?

4b9b3361

Ответ 1

Вам нужно реализовать шаблон репозитория, чтобы отделить проблемы WPF от EF

Затем вы можете использовать generics для уменьшения сложности EF для обработки CollectionViewSource

Хорошо спроектированный репозиторий должен уменьшать уровни кода и разрешать замену любой ORM (требуется для достойного тестирования)

Некоторые идеи для этого здесь

http://blog.nicktown.info/2008/12/10/using-a-collectionviewsource-to-display-a-sorted-entitycollection.aspx

Ответ 2

Кроме того, я не думаю, что вам нужно сделать ToList() здесь. Я полагаю, ObservableCollection() принимает IEnumerable, какие уже есть. Если вы делаете ToList, а затем передаете это ObservableCollection, то я думаю, что вы дважды проведете все свои записи.

familyOC = new ObservableCollection<Family>(families.ToList());

Вместо этого попробуйте это, что должно быть немного быстрее:

familyOC = new ObservableCollection<Family>(families);

Ответ 4

Мои рекомендации, если возможно, используют Expression Blend для проектирования вашего интерфейса, вместо кода Behind и вместо использования дизайнера Visual Studio это сэкономит вам много времени. Также попробуйте переосмыслить использование С# вместо xaml. Xaml не так уродлив, если вы делаете это "WPF Way". Часто, когда я думаю, что проще использовать код вместо xaml, это потому, что я делаю это неправильно и мне нужно переосмыслить, как лучше работать с WPF/xaml. Xaml отлично подходит, когда вы привыкнете к нему. Я также использовал структуру сущностей, которая еще не слишком велика. Я предпочитаю NHibernate.

Ответ 5

Я следил за этой ссылкой из своего блога и хотел упомянуть что-то еще, что я нашел с EF. Вид не по теме, но не полностью.

Я заметил некоторые сумасшедшие проблемы с производительностью с EF при использовании .Include. MS объясняет, почему в статье на своем веб-сайте я фактически начал переносить большую часть своего кода, чтобы вместо этого использовать метод .Load.

Потому что это утомительная задача, и потому, что я не мог найти другой способ сделать это... Я создал свой собственный метод под названием "IncludeByRoundTrip". Что он делает, это путь объекта и обеспечивает загрузку всего пути. Конечный результат такой же, как при использовании, однако, за кадром, я просто вызываю Load для всех свойств в графе объектов.

Это было бы похоже на выполнение чего-то вроде order.Load( "Customer.Address" ), если бы такой механизм существовал. В любом случае, проверьте это в своем блоге и дайте мне знать ваши выводы. Мне было бы интересно узнать, заметили ли другие замедление при использовании Include и если у вас есть другие подходы к атаке ситуации.

Более подробную информацию о моем решении можно найти по адресу: http://blog.nicktown.info/2009/07/27/method-to-load-an-entire-object-graph-using-adonet-entity-framework.aspx.

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

Ответ 6

Другим инструментом может быть BindableLINQ

Bindable LINQ - это набор расширений LINQ, которые добавляют возможности привязки данных и изменения к стандартным запросам LINQ