如何在Linq To Sql中的多个表上提交更改?

时间:2012-03-20 21:01:28

标签: database linq-to-sql windows-phone-7.1 datacontext notsupportedexception

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

日< -1 ----- * - > TrainingSession< -many ----- 1->运动

因此,一天可以举办许多培训课程,培训课程有一项运动。一项运动自然可以参加许多不同的训练课程。

主键看起来像这样: 日 - 日期时间 TrainingSession - int(生成数据库) 运动 - nvarchar(200)

体育将只有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可能来自于我没有将任何运动保存到数据库的事实,这可能是这样吗?

1 个答案:

答案 0 :(得分:0)

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

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

无论如何,事实证明我设置数据库结构的方式是正确的,没有什么必须在那里更改。

所以这就是我为了让它发挥作用而做的事情:
- 在提交关于当天的更改后,需要在培训课程中填写当天的方法。这是因为几天都有培训课程,而且我不能在数据库中已经存在的情况下保存培训课程。

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

(我将当天的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);
}

然后,通过培训课程填写当天的方法的更改如下:

-I打开一个using语句,我在其中实例化一个新的datacontext。然后我访问数据库以检索所有运动的列表,以及我需要更新的那一天。我发现需要通过dayItemParameter更新的那一天。 (请记住,从数据库中检索会为您提供一个集合。)

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

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

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

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();
        }
}

结论:

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

目前,我的应用程序正在运行,但它非常缓慢。在这个问题中,我只询问了一天,但在我的实际程序中,我创建了数百天,这意味着要打开和关闭数据库。如果有人有我的建议 优化过程,我是张开耳朵。

我意识到并且道歉这篇文章有这么长时间,但是写这篇文章帮助我更深入地理解了这种情况,我真的希望它也能帮助其他人。