【问题标题】:TransactionScope around Many to Many Insert with Entity Framework returns TimeoutException使用实体框架围绕多对多插入的 TransactionScope 返回 TimeoutException
【发布时间】:2015-06-24 12:52:44
【问题描述】:

当我尝试将新学生插入现有 schoolclassCode 时,为什么会收到 DbUpdateException - 没有更多详细信息?

这是一个多对多的关系。

var schoolclassCode = await context.SchoolclassCodes.SingleAsync(s => s.Id == pupil.SchoolclassCodeId);
schoolclassCode.Pupils.Add(pupil);
context.Entry(schoolclassCode).State = EntityState.Modified;
int count = await context.SaveChangesAsync();

是否必须先在 context.Pupils.add(pupil) 中插入瞳孔?

我认为我可以在 ONE 中插入学生并设置与学校课程代码的关系

schoolclassCode.Pupils.Add(pupil);

然后将 schoolclassCode 设置为已修改。

如何在与现有委托人/父实体的多对多关系中插入实体?

更新

System.Data.Entity.Infrastructure.DbUpdateException was unhandled by user code
  HResult=-2146233087
  Message=An error occurred while updating the entries. See the inner exception for details.
  Source=mscorlib
  StackTrace:
       bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       bei System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       bei TGB.Repository.PupilRepository.<AddPupil>d__8.MoveNext() in c:\Repository\TGB\TGB.Repository\PupilRepository.cs:Zeile 29.
    --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
       bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       bei System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       bei Business.IntegrationTests.PupilRepositoryTests.CreatePupil() in c:\TGB\IntegrationTests\PupilRepositoryTests.cs:Zeile 31.
  InnerException: System.Data.Entity.Core.UpdateException
       HResult=-2146233087
       Message=An error occurred while updating the entries. See the inner exception for details.
       Source=EntityFramework
       StackTrace:
            bei System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.<UpdateAsync>d__0.MoveNext()
         --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
            bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            bei System.Data.Entity.Core.Objects.ObjectContext.<ExecuteInTransactionAsync>d__3d`1.MoveNext()
         --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
            bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            bei System.Data.Entity.Core.Objects.ObjectContext.<SaveChangesToStoreAsync>d__39.MoveNext()
         --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
            bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            bei System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<ExecuteAsyncImplementation>d__9`1.MoveNext()
         --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
            bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            bei System.Data.Entity.Core.Objects.ObjectContext.<SaveChangesInternalAsync>d__31.MoveNext()
       InnerException: System.Data.SqlClient.SqlException
            HResult=-2146232060
            Message=Timeout abgelaufen. Das Zeitlimit wurde vor dem Beenden des Vorgangs überschritten oder der Server reagiert nicht.
            Source=.Net SqlClient Data Provider
            ErrorCode=-2146232060
            Class=11
            LineNumber=0
            Number=-2
            Procedure=""
            Server=MyAccount\SQLEXPRESS
            State=0
            StackTrace:
                 bei System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
                 bei System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
                 bei System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
                 bei System.Data.SqlClient.SqlCommand.EndExecuteNonQueryInternal(IAsyncResult asyncResult)
                 bei System.Data.SqlClient.SqlCommand.EndExecuteNonQueryAsync(IAsyncResult asyncResult)
                 bei System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
              --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
                 bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
                 bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                 bei System.Data.Entity.Utilities.TaskExtensions.CultureAwaiter`1.GetResult()
                 bei System.Data.Entity.Core.Mapping.Update.Internal.DynamicUpdateCommand.<ExecuteAsync>d__0.MoveNext()
              --- Ende der Stapelüberwachung vom vorhergehenden Ort, an dem die Ausnahme ausgelöst wurde ---
                 bei System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
                 bei System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
                 bei System.Data.Entity.Core.Mapping.Update.Internal.UpdateTranslator.<UpdateAsync>d__0.MoveNext()
            InnerException: System.ComponentModel.Win32Exception
                 HResult=-2147467259
                 Message=Der Wartevorgang wurde abgebrochen
                 ErrorCode=-2147467259
                 NativeErrorCode=258
                 InnerException: 

更新 2

public class SchoolclassCode
{
    public SchoolclassCode()
    {
        Pupils = new HashSet<Pupil>();
    }

    public int Id { get; set; }
    public ISet<Pupil> Pupils { get; set; }

}

public class Pupil
{
    public Pupil()
    {
         SchoolclassCodes = new HashSet<SchoolclassCode>();
    }

    public int Id { get; set; }
    public ISet<SchoolclassCode> SchoolclassCodes { get; set; }

    [NotMapped]
    public int SchoolclassCodeId { get; set; }
}

实际上,多对多关系应该按照惯例起作用,但由于我无法解释的 DbUpdateException 行为,我仍然明确设置了 SchoolclassCode 和 Pupil 之间的配置。

public class SchoolclassCodeConfiguration : EntityTypeConfiguration<SchoolclassCode>
{
    public SchoolclassCodeConfiguration()
    {
        base.Property(p => p.SchoolclassNumber).IsRequired().HasMaxLength(10);
        base.Property(p => p.SubjectName).IsRequired().HasMaxLength(10);
        base.Property(p => p.ClassIdentifier).IsOptional().HasMaxLength(2);
        base.HasMany(p => p.Pupils)
        .WithMany(p => p.SchoolclassCodes)
        .Map(x =>
        {
            x.MapLeftKey("SchoolclassCodeId");
            x.MapRightKey("PupilId");
            x.ToTable("SchoolclassCodePupil");
        });
    }
}

LOG ERRORS发生在我的 Attach Pupil 方法中的 SaveChanges 上

UPDATE [dbo].[SchoolclassCode]
SET [SchoolclassNumber] = @0, [SubjectName] = @1, [Color] = @2, [ClassIdentifier] = @3, [SchoolyearId] = @4
WHERE ([Id] = @5)

-- @0: '7' (Type = String, Size = 10)

-- @1: 'Math' (Type = String, Size = 10)

-- @2: '5' (Type = Int32)

-- @3: 'a' (Type = String, Size = 2)

-- @4: '1' (Type = Int32)

-- @5: '1' (Type = Int32)

-- Executing asynchronously at 24.06.2015 16:57:57 +02:00

-- Completed in 8 ms with result: 1

INSERT [dbo].[Pupil]([FirstName], [LastName], [Postal], [City], [Street])
VALUES (@0, @1, NULL, NULL, NULL)
SELECT [Id]
FROM [dbo].[Pupil]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()


-- @0: 'Max' (Type = String, Size = 25)

-- @1: 'Mustermann' (Type = String, Size = 25)

-- Executing asynchronously at 24.06.2015 16:49:30 +02:00

-- Completed in 2 ms with result: SqlDataReader



INSERT [dbo].[SchoolclassCodePupil]([SchoolclassCodeId], [PupilId])
VALUES (@0, @1)

-- @0: '1' (Type = Int32)

-- @1: '1' (Type = Int32)

-- Executing asynchronously at 24.06.2015 16:49:30 +02:00

-- Completed in 2 ms with result: 1



Committed transaction at 24.06.2015 16:49:30 +02:00

Closed connection at 24.06.2015 16:49:30 +02:00

The thread 0x60 has exited with code 259 (0x103).
The thread 0x1178 has exited with code 259 (0x103).
The thread 0xdc0 has exited with code 259 (0x103).
A first chance exception of type 'System.NullReferenceException' occurred in Business.IntegrationTests.dll

真正的问题

是我注释掉的每个测试之前和之后的 TransactionScope,然后一切正常!

为什么我在使用此代码时会收到此异常 - 其他测试 + TransactionScope 工作正常!!! -

public abstract class IntegrationTestsBase
    {
        protected TransactionScope TransactionScope;

        [TestInitialize]
        public void TestSetup()
        {
            TransactionScope = new TransactionScope();
        }

        [TestCleanup]
        public void TestCleanup()
        {
            TransactionScope.Dispose();
        }
    }

【问题讨论】:

  • DbUpdateException 通常表示数据库级别出现问题,而不是 EF 级别。通常,内部异常会有更多有趣的细节。你能发布完整的异常堆栈跟踪吗?
  • 很好认!请参阅我更新的问题。真正的错误并不多。但是错误来源是sql数据提供者而不是EF。
  • 我还更新了两个参与实体的问题,以防仍有问题......
  • 我无法翻译,但听起来你有超时? Timeout abgelaufen. Das Zeitlimit wurde vor dem Beenden des Vorgangs überschritten oder der Server reagiert nicht.。也许您可以尝试记录生成的 SQL 语句以查看它们有什么问题,添加以下代码:context.Database.Log = s =&gt; Debug.WriteLine(s);
  • 使用日志记录详细信息更新了问题,并通过更新 SchoolclassCode 更正了日志记录详细信息!

标签: c# entity-framework entity-framework-6.1


【解决方案1】:

阅读此链接后:Get TransactionScope to work with async / await

我知道我处于那种情况:

“在 .NET Framework 4.5.1 中,有一组新的 TransactionScope 构造函数,它们采用 TransactionScopeAsyncFlowOption 参数。 根据 MSDN,它支持跨线程延续的事务流。”

TransactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);

TransactionScope 的正确参数将使我的集成​​测试现在运行绿色 :-) 祝 TDD 快乐!!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-02
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多