0

我正在制作一个 Windows Phone 7.1 应用程序,但在将更改提交到我的数据库时遇到了很多麻烦。这是我数据库中表的结构:

第 <-1--*-> 天训练课 <----1-> 运动

所以,一天可以有很多训练课,而一个训练课有一项运动。一项运动自然可以在许多不同的训练课程中进行。

主键如下所示:Day - DateTime TrainingSession - int(DB 生成) Sport - nvarchar(200)

Sports 将仅具有属性 sportName 和 iconFileName。

我通过将 EntitySet 放在 Day 和 Sport 中来建立关联,并且 TrainingSession 具有 EntityRef 和 EntityRef。我不是 100% 确定 Sport 是否需要 EntitySet,所以如果我错了,请纠正我。目前,我只是在我的 Sport 类中对一些运动进行了硬编码以进行测试,您会看到我检索了一个 ObservableCollection 以将它们取出。

以下是我如何尝试创建一组包含训练课程的日子,每个训练课程都有不同的运动:

    public void CreateDay(DateTime date)
    {
        FitPlanDataContext calendarDatabase = new FitPlanDataContext(FitPlanDataContext.ConnectionString);
        DateTime firstDate = new DateTime(date.Year, date.Month, 1);

        DayItem dayItem = new DayItem();
        dayItem.DateTime = firstDate;

        fillTestDayItemWithRandomData(dayItem);

        calendarDatabase.DayItems.InsertOnSubmit(dayItem);
        calendarDatabase.SubmitChanges();
    }

    private void fillTestDayItemWithRandomData(DayItem dayItem)
    {
        ObservableCollection<SportArt> sportArtCollection = SportArtController.GetAllSports();

        dayItem.TrainingSessions = new EntitySet<TrainingSession>();
        ObservableCollection<TrainingSession> trainingSessionCollection = new ObservableCollection<TrainingSession>();

        TrainingSession trainingSession1 = new TrainingSession();
        trainingSession1.DayItem = dayItem;
        trainingSession1.SportArt = sportArtCollection[1];
        trainingSessionCollection.Add(trainingSession1);

        TrainingSession trainingSession2 = new TrainingSession();
        trainingSession2.DayItem = dayItem;
        trainingSession2.SportArt = sportArtCollection[2];
        trainingSessionCollection.Add(trainingSession2);

        FitPlanDataContext calendarDatabase = new FitPlanDataContext(FitPlanDataContext.ConnectionString);
        calendarDatabase.TrainingSessions.InsertAllOnSubmit<TrainingSession>(trainingSessionCollection);
    }

这段代码对我不起作用,它给了我以下错误:

NotSupportedException 未处理:已尝试附加或添加一个不是新的实体,可能是从另一个 DataContext 加载的。这是不支持的。

在我得到这个错误之前,我也得到了 NullReferenceExceptions。

我一直在寻找解决方案,我看到有些人使用 Detach 或带有 Attach 的解决方法,但我还没有弄清楚如何将它实现到我的代码中。有人可以帮我解决这个问题吗?

另外,我认为 NullReferenceException 可能来自我没有将任何运动保存到数据库的事实,可能是这样吗?

4

1 回答 1

0

所以我搞砸了很多,今天我终于找到了我正在寻找的解决方案。

看来我问错了问题。我没有包含来自数据库的查询,这可能很重要。我实际上省略了很多代码以使我的问题保持简单,但看起来我省略了太多。

无论如何,事实证明我设置数据库结构的方式是正确的,并且不需要在那里进行任何更改。

因此,这就是我为使其正常工作所做的工作:
- 调用该方法,该方法在提交当天的更改后需要进行培训课程。这是因为天有培训课程,如果没有数据库中的天,我无法保存培训课程。

- 我在需要使用数据上下文的地方添加了 using 语句,而不是仅使用局部变量创建数据上下文的实例。这确保了数据上下文只存在于 using 语句的范围内。

(我将当天的 DateTime 更改为作为方法参数给出的日期)

public void CreateDay(DateTime date)
{
    DayItem dayItem = new DayItem();
    dayItem.DateTime = date;

        using (FitPlanDataContext calendarDatabase = new FitPlanDataContext(FitPlanDataContext.ConnectionString))
        {
            calendarDatabase.DayItems.InsertOnSubmit(dayItem);
            calendarDatabase.SubmitChanges();                 
        }

    fillTestDayItemWithRandomData(dayItem);
}

然后,对每天进行培训的方法的更改如下:

-我打开一个 using 语句,在其中实例化一个新的数据上下文。然后我访问数据库以检索所有运动的列表,以及我需要更新的日期。我通过 dayItemParameter 找到需要更新的日期。(请记住,从数据库中检索会给您一个集合。)

-我创建了新的培训课程并填写了他们的属性。请注意,我从数据库中检索到的日期是培训课程属性的值,因为培训课程是当天的孩子,并且需要知道其父日期是谁。

-我删除了 EntitySet 的实例化,因为我意识到我已经在 DayItem 类的构造函数中实例化了它。

-最后,我将所有新的培训课程添加到一个集合中,并使用 InsertAllOnSubmit(collection) 将它们一次全部保存到数据库中。

private void fillTestDayItemWithRandomData(DayItem dayItemParameter)
{
        using (FitPlanDataContext calendarDatabase = new FitPlanDataContext(FitPlanDataContext.ConnectionString))
        {
            ObservableCollection<SportArt> sportArtCollection;          
            var sportArts = (from SportArt sportArt in calendarDatabase.SportArts
                                 select sportArt);
            sportArtCollection = new ObservableCollection<SportArt>(sportArts);

            ObservableCollection<DayItem> dayItemCollection;
            var dayItems = (from DayItem dayItem in calendarDatabase.DayItems
                            where dayItem.DateTime == dayItemParameter.DateTime
                            select dayItem);
            dayItemCollection = new ObservableCollection<DayItem>(dayItems);

            DayItem foundDayItem = dayItemCollection[0];

            ObservableCollection<TrainingSession> trainingSessionCollection = new ObservableCollection<TrainingSession>();

            TrainingSession trainingSession1 = new TrainingSession();
            trainingSession1.DayItem = foundDayItem;
            trainingSession1.SportArt = sportArtCollection[1];
            trainingSessionCollection.Add(trainingSession1);

            TrainingSession trainingSession2 = new TrainingSession();
            trainingSession2.DayItem = foundDayItem;
            trainingSession2.SportArt = sportArtCollection[2];
            trainingSessionCollection.Add(trainingSession2);


            calendarDatabase.TrainingSessions.InsertAllOnSubmit<TrainingSession>(trainingSessionCollection);
            calendarDatabase.SubmitChanges();
        }
}

结论:

我遇到的主要问题是我试图将培训课程保存到未提交到数据库的日期。下一个大问题(我认为许多其他人都有)是实体的读取和更新必须在同一个数据上下文中。因此,您不能创建数据上下文来检索一天,然后使用另一个数据上下文将训练课程添加到该天(即使您将当天的值保存到局部变量)。您需要在同一数据上下文中检索当天并将培训课程保存到其中。

目前,我的应用程序正在运行,但速度很慢。在这个问题中,我问的只是一天,但在我的实际程序中,我创建了数百天,这意味着数据库的大量打开和关闭。如果有人对我如何优化流程有建议,我愿意倾听。

我意识到并且很抱歉这篇文章写了这么长,但是写下来帮助我更深入地了解了情况,我真的希望它也能对其他人有所帮助。

于 2012-03-21T18:50:17.307 回答