2013-05-09 40 views
0

首先让我解释一下,我完全理解为什么这个InvalidOperationException已被抛出,而且我只是在寻找一种方法来避免它从被抛出。有一个电话System.Linq.Enumerable.SingleOrDefault(),我可以在Visual Studio 2010 Call Stack窗口中看到。但是,该呼叫是在外部Linq2Sql的代码中,所以我无法更改它。'序列包含多个元素'(InvalidOperationException)在使用Linq2Sql时由外部System.Core调用引发

Call Stack showing (mostly) external code. (对不起,你可能需要放大才能看到这个图像正常)

最后的内部代码执行呼叫转到外部应用程序dbml.designer.cs文件,我有机会获得被发现之前,但仍无法编辑,因为它会自动更新并丢失自定义更改。它是在一个(Linq2Sql)的属性设置为应用程序使用的数据库表中的一个,看来,这个问题是由呼叫造成的_DbAudioTrackContributors.Entity对象:

public DbAudioTrackContributor DbAudioTrackContributors 
{ 
    get 
    { 
     return this._DbAudioTrackContributors.Entity; 
    } 
    set 
    { 
     // This is the last internal line before the Exception 
     DbAudioTrackContributor previousValue = this._DbAudioTrackContributors.Entity; 

     // Execution never reaches here 
     if (((previousValue != value) || 
     (this._DbAudioTrackContributors.HasLoadedOrAssignedValue == false))) 
     { 
      this.SendPropertyChanging(); 
      if ((previousValue != null)) 
      { 
       this._DbAudioTrackContributors.Entity = null; 
       previousValue.DbAudioTrack = null; 
      } 
      this._DbAudioTrackContributors.Entity = value; 
      if ((value != null)) 
      { 
       value.DbAudioTrack = this; 
      } 
      this.SendPropertyChanged("DbAudioTrackContributors"); 
     } 
    } 
} 

如果有人有办法为我提供与EntityRef<TEntity>结构的内部代码(甚至只是Entity属性),这可能可以帮助我找出造成问题的原因。

我自己的代码InvalidOperationException前的最后一行抛出是dataContext.SubmitChanges()呼叫:

public int UpdateAudioTrack(AudioTrack audioTrack) 
{ 
    using (TransactionScope transactionScope = new TransactionScope()) 
    { 
     using (MidasDataContext dataContext = DataContext) 
     { 
      DbAudioTrack dbAudioTrack = dataContext.DbAudioTracks.Where(
       g => g.Id == audioTrack.Id).FirstOrDefault(); 
      if (dbAudioTrack == null) return -1; 
      CopyToDbAudioTrack(audioTrack, dbAudioTrack); 
      UpdateAudioTrackContributors(dataContext, audioTrack); 

      // This is the last line of my code before the Exception 
      dataContext.SubmitChanges(ConflictMode.FailOnFirstConflict); 

      // Execution never reaches here 
      transactionScope.Complete(); 
      return 0; 
     } 
    } 
} 

CopyToDbAudioTrack方法简单地复制所有的属性值从AudioTrack对象到Linq2Sql产生DbAudioTrack对象,下面显示了UpdateAudioTrackContributors方法。

private void UpdateAudioTrackContributors(MidasDataContext dataContext, AudioTrack audioTrack) 
{ 
    DataList<Label> labels = new DataList<Label>(
     audioTrack.Labels.Except(audioTrack.OriginalState.Labels)); 
    if (labels.Count > 0) AddAudioTrackContributors(dataContext, audioTrack, labels); 
    labels = new DataList<Label>(audioTrack.OriginalState.Labels.Except(audioTrack.Labels)); 
    if (labels.Count > 0) DeleteAudioTrackContributors(dataContext, audioTrack, labels); 
} 

此方法仅发现已经改变,要么添加或删除他们在AudioTrackContributors数据库表中的Label对象。此表似乎是问题的根源,因为如果此代码被注释掉,它将消失。但是,这种方法正确地选择要添加或删除的对象,所以我仍然感到困惑。该AddAudioTrackContributors方法基本上调用如下所示的代码和DeleteAudioTrackContributors代码如下所示的是:

List<DbAudioTrackContributor> dbAudioTrackContributors = new List<DbAudioTrackContributor>(); 
foreach (T dataListEntry in dataList) 
{ 
    DbAudioTrackContributor dbAudioTrackContributor = new DbAudioTrackContributor(); 
    CopyToDbAudioTrackContributor(audioTrack, dataListEntry, dbAudioTrackContributor, contributorType); 
    dbAudioTrackContributors.Add(dbAudioTrackContributor); 
} 
dataContext.DbAudioTrackContributors.InsertAllOnSubmit(dbAudioTrackContributors); 

DeleteAudioTrackContributors

List<DbAudioTrackContributor> dbAudioTrackContributors = new List<DbAudioTrackContributor>(); 
foreach (T dataListEntry in dataList) 
{ 
    DbAudioTrackContributor dbAudioTrackContributor = dataContext.DbAudioTrackContributors.Where(d => d.DataListId == dataListEntry.Id && d.AudioTrackId == audioTrack.Id).FirstOrDefault(); 
    if (dbAudioTrackContributor != null) dbAudioTrackContributors.Add(dbAudioTrackContributor); 
} 
dataContext.DbAudioTrackContributors.DeleteAllOnSubmit(dbAudioTrackContributors); 

同样,通过执行过程中的代码步进示出的是,上述代码亦正确地选择删除正确的对象。由于我在代码中看不到任何问题,因此我不知道接下来要看什么。

如果任何人有任何想法如何进行,我会很高兴听到他们。提前谢谢了。

+0

DbAudioTrackContributors设置程序中的哪一行是7717? – 2013-05-10 11:41:18

+0

这是在执行到外部之前的最后一次内部代码调用 - 第一个代码示例中标记的行。 但是,我现在已经设法解决了这个问题,但是感谢您的关注。 – Sheridan 2013-05-10 11:55:01

回答

1

好吧,所以这是一个可怕的问题,没有明确的线索关于实际原因。原来是Linq2Sql dbml文件中DbAudioTrackContributor表的定义。

幸运的是,我也有一个DbMasterTrackContributor表没有遭受同样的错误。比较了所有与两张表和这次更新相关的代码后,我发现没有区别。然后,我决定查看Linq2Sql生成的设计器代码,并注意到两个表定义之间的差异。

DbAudioTrackContributor表被注册为EntityRef<DbAudioTrackContributor>,而工作DbMasterTrackContributor表被注册为EntitySet<DbMasterTrackContributor>

在网上查看它们之间的差异后,结果发现EntityRef<T>用于一对一关系,EntitySet<T>用于一对多和多对多的关系。因此,我怀疑它们都应该被声明为EntitySet<T>,所以我从dbml文件中删除了表,然后重新添加它。

这样做后,它又开始工作了!所以我学到了一个宝贵的教训:如果我有一个与dbml相关的错误,首先尝试从dbml文件中删除并重新添加可疑表。

相关问题