【问题标题】:How do I SubmitChanges on multiple tables that are related in LinqToSql?如何在 LinqToSql 中相关的多个表上提交更改?
【发布时间】:2012-03-20 21:01:27
【问题描述】:

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

Day TrainingSession 运动

因此,一天可以有很多训练课,而一个训练课只有一项运动。一项运动自然可以参加许多不同的训练课程。

主键如下所示: 日期 - 日期时间 TrainingSession - int(数据库生成) 运动 - 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 可能是因为我没有将任何运动保存到数据库中,是这样吗?

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    -我在需要使用数据上下文的地方添加了 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();
            }
    }
    

    结论:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-27
      • 2011-06-26
      • 1970-01-01
      • 2013-08-19
      • 1970-01-01
      • 2020-11-03
      相关资源
      最近更新 更多