1

我正在努力更新数据库中现有讲师的数据。
每个讲师都有他/她教授的NameAcademicDegreeCourses ( Courses==Lessons)。

实际上有更多的属性,class Lecturer但它们不相关。为简单起见,我们假设POCO类是这样定义的:

// POCO class (Entity Framework Reverse Engineering Code First)
public class Lecturer
{
    public Lecturer()
    {
        this.Courses = new List<Course>();
    }

    public int Id_Lecturer { get; set; } // Primary Key
    public string Name { get; set; }
    public int? Academic_Degree_Id { get; set; }
    public virtual AcademicDegree AcademicDegree { get; set; }
    public virtual ICollection<Course> Courses { get; set; }
}

数据访问层中,我有方法应该更新等于(使用,和)void UpdateLecturer(Lecturer lecturer)的讲师。Id_Lecturerlecturer.Id_Lecturerlecturer.Namelecturer.AcademicDegreelecturer.Courses

这是非常方便的方法,因为在ViewModel中我可以调用_dataAccess.UpdateLecturer(SelectedLecturer)(在XAMLSelectedLecturer中绑定的位置;属性可以由用户在es 和中设置)。SelectedLecturerTextBoxCheckbox

不幸的是这种方法:

    public void UpdateLecturer(Lecturer lecturer)
    {
        using(var db = new AcademicTimetableDbContext())
        {
            // Find lecturer with Primary Key set to 'lecturer.Id_Lecturer':
            var lect = db.Lecturers.Find(lecturer.Id_Lecturer);

            // If not found:
            if (lect == null)
                return;

            // Copy all possible properties:
            db.Entry(lect).CurrentValues.SetValues(lecturer);
            // Everything was copied except 'Courses'. Why?!

            // I tried to add this, but it doesn't help:
            // var stateMgr = (db as IObjectContextAdapter).ObjectContext.ObjectStateManager;
            // var stateEntry = stateMgr.GetObjectStateEntry(lect);
            // stateEntry.SetModified();

            db.SaveChanges();
        }
    }

更新所有内容(即Id_Lecturer、和)Name,但 .之后不变的除外Academic_Degree_IdAcademicDegree Coursesdb.SaveChanges()

为什么?我该如何解决?


类似的问题:


- 编辑 -

我也尝试过这种方式(想法来自这篇文章):

public void UpdateLecturer(Lecturer lecturer)
{
    using (var db = new AcademicTimetableDbContext())
    {
        if (lecturer == null)
            return;

        DbEntityEntry<Lecturer> entry = db.Entry(lecturer);

        if (entry.State == EntityState.Detached)
        {
            Lecturer attachedEntity = db.Set<Lecturer>().Find(lecturer.Id_Lecturer);

            if (attachedEntity == null)
                entry.State = EntityState.Modified;
            else
                db.Entry(attachedEntity).CurrentValues.SetValues(lecturer);
        }

        db.SaveChanges();
    }
}

课程仍然不会覆盖旧值。


-- 编辑 2 --

作为对@Slauma 问题的回应,我将描述我是如何加载的(作为参数SelectedLecturer传递给方法)。UpdateLecturer(Lecturer lecturer)

我正在实施MVVM概念,因此我的解决方案中有View项目,并设置为. 在视图中有从数据库中获取的所有讲师的列表。以这种方式绑定:DataContextLecturerListViewModelDataGridDataGrid

<DataGrid AutoGenerateColumns="False" Name="LecturersDataGrid" HeadersVisibility="Column" IsReadOnly="True" ItemsSource="{Binding Lecturers,Mode=TwoWay}" SelectedItem="{Binding SelectedLecturer, Mode=TwoWay}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
        <DataGridTextColumn Header="Academic degree" Binding="{Binding AcademicDegree.Degree_Name}" />
        <DataGridTemplateColumn>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Button Content="Edit" Click="EditButtonClick"/>
                        <Button Content="Delete" Command="{Binding DataContext.RemoveLecturer, ElementName=LecturersDataGrid}" />
                    </StackPanel>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>

LecturersLecturerListViewModel以这种方式从构造函数中的数据库中获取:

///
/// Code within LecturerListViewModel class:
///

// All lecturers from database.
public ObservableCollection<Lecturer> Lecturers

// Constructor
public LecturerListViewModel()
{
    // Call to Data Access Layer:
    Lecturers = new ObservableCollection<Lecturer>(_dataAccess.GetAllLecturers());

    // Some other stuff here...
}

private Lecturer _selectedLecturer;

// Currently selected row with lecturer.
public Lecturer SelectedLecturer
{
    get { return _selectedLecturer; }
    set { SetProperty(out _selectedLecturer, value, x => x.SelectedLecturer); }
}

///
/// Data Access Layer (within DataAccess class):
/// 

public IEnumerable<Lecturer> GetAllLecturers()
{
    using (var dbb = new AcademicTimetableDbContext())
    {
        var query = from b 
                    in dbb.Lecturers.Include(l => l.AcademicDegree).Include(l => l.Timetables).Include(l => l.Courses)
                    select b;
        return query.ToList();
    }
}
4

1 回答 1

2

将状态设置为Modified并且仅更新实体SetValues的标量属性。Lecturer更新Courses集合(它不是一个标量属性)需要更多的工作。您必须处理课程可能已从集合中删除、课程可能已添加或课程的标量属性可能已修改的情况。

此外,更新集合的方式取决于课程是否依赖于讲师。课程从集合中删除后是否需要从数据库中删除,还是只需要删除讲师和课程之间的关系?新课程添加到集合时是否需要创建新课程,还是只需要建立关系?

如果不需要删除课程并且没有创建新课程,则 Update 方法可能如下所示:

public void UpdateLecturer(Lecturer lecturer)
{
    using(var db = new AcademicTimetableDbContext())
    {
        if (lecturer == null)
            return;

        var lecturerInDb = db.Lecturers
            .Include(l => l.Courses)
            .Single(l => l.Id_Lecturer == lecturer.Id_Lecturer);

        // Update lecturer
        db.Entry(lecturerInDb).CurrentValues.SetValues(lecturer);

        // Remove courses relationships
        foreach (var courseInDb in lecturerInDb.Courses.ToList())
            if (!lecturer.Courses.Any(c => c.Id_Course == courseInDb.Id_Course))
                lecturerInDb.Courses.Remove(courseInDb);

        foreach (var course in lecturer.Courses)
        {
            var courseInDb = lecturerInDb.Courses.SingleOrDefault(
                c => c.Id_Course == course.Id_Course);
            if (courseInDb != null)
                // Update courses
                db.Entry(courseInDb).CurrentValues.SetValues(course);
            else
            {
                // Add courses relationships
                db.Courses.Attach(course);
                lecturerInDb.Courses.Add(course);
            }
        }
    }

    db.SaveChanges();
}

根据您的场景的详细信息,正确的解决方案可能会略有不同。

编辑

如果集合中的课程对(可能具有导航属性)lecturer.Courses有引用,则在将此集合中的课程附加到上下文时可能会遇到问题,因为已经附加并且具有相同的键。您可以尝试像这样更改最后一个块以希望解决问题:lecturerLecturerlecturerInDbelse

            else
            {
                // Add courses relationships
                var courseToAttach = new Course { Id_Course = course.Id_Course };
                db.Courses.Attach(courseToAttach);
                lecturerInDb.Courses.Add(courseToAttach);
            }
于 2012-11-14T08:52:33.770 回答