none
EntityFramework и Combobox.SelectedItem RRS feed

  • Вопрос

  • В базе данных есть таблицы: Employees и Appointments (сотрудники и должности).

    В Employees есть поле Appointment [int32], которое ссылается на Appointments.id

    Для БД автоматически создана EntityModel "Geocomplex.edmx"

    Необходимо сделать редактирование и просмотр данных работника.

    Данные получаются из базы стандартно:

    public EmployeesWindow()
    {
    	InitializeComponent();
    	GeocomplexEntities context = new GeocomplexEntities();
    	lbxEmployees.ItemsSource = context.Employees.ToList();
    }

    Отображаются, насколько я понимаю тоже стандартно.

    Привязываем DataContext к текущему выбранному сотруднику:

    <Grid DataContext="{Binding ElementName=lbxEmployees, Path=SelectedItem}">


    Выводим информацию о нем в элементы управления:

    <TextBlock Text="{Binding Path=Appointment.Name}" Grid.Column="1" d:DataContext="{d:DesignInstance CompanyDb:Employee}" Grid.Row="1" />
    <ComboBox ItemsSource="{Binding Source={StaticResource Appointments}}" SelectedItem="{Binding Appointment}" Grid.Column="1" d:DataContext="{d:DesignInstance CompanyDb:Employee}" Grid.Row="2">
    	<ComboBox.ItemTemplate>
    		<DataTemplate>
    			<TextBlock Text="{Binding Path=Name}"/>
    		</DataTemplate>
    	</ComboBox.ItemTemplate>
    </ComboBox>

    , где StaticResource Appointments это ObjectDataProvider

    <ObjectDataProvider

    x:Key="Appointments"

    ObjectType="{x:Type CompanyDb:Catalog}"

    MethodName="GetAppointments"> </ObjectDataProvider>

    Класс Catalog, созданный для ObjectDataProvider:

    public class Catalog
    {
    	public List<Appointment> Appointments { get; set; }
    	public Catalog()
    	{
    		GeocomplexEntities context = new GeocomplexEntities();
    		Appointments = context.Appointments.ToList();
    
    	}
    
    	public List<Appointment>  GetAppointments()
    	{
    		return Appointments;
    	}
    }

    Вроде бы все правильно, но при открытии в ComboBox не показывается должность (пустое поле). Однако, при изменении его, одновременно изменяется и TextBlock.

    Почему-то одинаковые Appointment, полученные в разное время при сравнении получаются разными. Я попробовал переопределить метод Equals автоматически генерируемого класса Appointment, возвращая true при одинаковом Id, все заработало.

    Однако, когда я поменял что-то в базе данных и сделал "Update model from database", мои изменения были удалены и классы сгенерированы заново.

    Подскажите, в чем причина "неодинаковости" и как мне решить задачу? Только начинаю разбираться в EntityFramework по примерам, возможно все делаю не так


    10 июня 2013 г. 13:33

Ответы

  • "Одинаковые" они в вашем понимании, т.к. имеют одинаковые Имена, названия, ID'шники и т.д. Программа же не знает по каким параметрам определять равенство сущностей и поэтому она сравнивает их по ссылкам, которые естественно у ваших объектов будут разными. Вы верно сделали, что переопределили Equals и GetHashCode только переопределите их в отдельном partial-классе для необходимой сущности. Таким образом вы избавитесь от переписывания логики сравнения при каждом вызове "Update model from database", правда придется проставить ключевое слово partial у сущностей.
    11 июня 2013 г. 3:25

Все ответы

  • "Одинаковые" они в вашем понимании, т.к. имеют одинаковые Имена, названия, ID'шники и т.д. Программа же не знает по каким параметрам определять равенство сущностей и поэтому она сравнивает их по ссылкам, которые естественно у ваших объектов будут разными. Вы верно сделали, что переопределили Equals и GetHashCode только переопределите их в отдельном partial-классе для необходимой сущности. Таким образом вы избавитесь от переписывания логики сравнения при каждом вызове "Update model from database", правда придется проставить ключевое слово partial у сущностей.
    11 июня 2013 г. 3:25
  • Чуть расширю. EF, по крайней мере в версии 5, генерирует все классы как Partial. Т.е. у вас есть файл с классом вида:

    public partial class Appointment
    {
        ...

    Добавляете в проект еще один класс (файл только назовите как нибудь Appointment.partial.cs). А у самого класса объявление сделайте как в исходном классе сгенерированном EF. Ну и переопределяйте те свойства, которые вам нужны.

    Например, у нас для класса Person переопределен метод ToString:

    public partial class Person
    {
        public override string ToString()
        {
            return String.Format("{0} {1} {2}",
                                    LastName,
                                    FirstName,
                                    Middlename);
        }
    }

    11 июня 2013 г. 5:21
    Отвечающий