mtanneryd / ef-bulk-operations

Bulk operations for Entity Framework 6

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

InvalidOperationExceptions with BulkInsertAll

thomasgalliker opened this issue · comments

Hi @mtanneryd, thank you for the effort you put into this library. I tried the latest beta version but I could not get it work.

The relevant position of code looks like this: I'm opening a new transaction and trying to recursively insert a list of employeesTestData.

using (var transaction = employeeContext.Database.BeginTransaction()) { var insertRequest = new BulkInsertRequest<Employee> { Recursive = true, Entities = employeesTestData, Transaction = (SqlTransaction)transaction.UnderlyingTransaction }; employeeContext.BulkInsertAll(insertRequest); transaction.Commit(); }

Method call BulkInsertAll(...) throws the following 'Sequence contains no matching element' and one line later, the Commit(...) raises the 'There is already an open DataReader' exception. What am I doing wrong? I forked your code and could fix it to make it work. But I rather think I'm doing something wrong here. Thanks for your help, Thomas.

System.InvalidOperationException HResult=0x80131509 Message=Sequence contains no matching element Source=System.Core StackTrace: at System.Linq.Enumerable.Single[TSource](IEnumerable1 source, Func2 predicate) at Tanneryd.BulkOperations.EF6.DbContextExtensions.GetMappings(DbContext ctx, Type t) at Tanneryd.BulkOperations.EF6.DbContextExtensions.DoBulkInsertAll(DbContext ctx, IList1 entities, SqlTransaction transaction, Boolean recursive, Boolean allowNotNullSelfReferences, Dictionary2 savedEntities, BulkInsertResponse response) at Tanneryd.BulkOperations.EF6.DbContextExtensions.BulkInsertAll[T](DbContext ctx, BulkInsertRequest1 request)
at EntityFramework.Toolkit.Tests.PerformanceTests.AddEntitiesPerformanceTest_BulkInsert(Int32 count) in C:\src\github\thomasgalliker\EntityFramework.Toolkit\ EntityFramework.Toolkit.Tests\PerformanceTests.cs:line 147

System.InvalidOperationException
HResult=0x80131509
Message=There is already an open DataReader associated with this Command which must be closed first.
Source=System.Data
StackTrace:
at System.Data.SqlClient.SqlInternalConnectionTds.ValidateConnectionForExecute(SqlCommand command)
at System.Data.SqlClient.SqlInternalTransaction.Rollback()
at System.Data.SqlClient.SqlTransaction.Dispose(Boolean disposing)
at System.Data.Entity.Infrastructure.Interception.InternalDispatcher1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action2 operation, TInterceptionContext interceptionContext, Action3 executing, Action3 executed)
at System.Data.Entity.Infrastructure.Interception.DbTransactionDispatcher.Dispose(DbTransaction transaction, DbInterceptionContext interceptionContext)
at System.Data.Entity.Core.EntityClient.EntityTransaction.Dispose(Boolean disposing)
at System.Data.Entity.DbContextTransaction.Dispose(Boolean disposing)
at System.Data.Entity.DbContextTransaction.Dispose()
at EntityFramework.Toolkit.Tests.PerformanceTests.AddEntitiesPerformanceTest_BulkInsert(Int32 count) in C:\src\github\thomasgalliker\EntityFramework.Toolkit\ EntityFramework.Toolkit.Tests\PerformanceTests.cs:line 150
`

Hello Thomas!

I could not find your perf test code on github so I was not able to try it out. There are two places in GetMappings where I use Single(). The first time is when I try to get the entity set maps out of the context. This has never failed for me but if you are using edmx rather then DbContext that might explain it. The ef6-bulk-operations package has only been tested with DbContext. The second use of Single() occurs if there is a many-to-many relationship. Do you have such a relationship in the employee or in any dependent class?

DbContext is a code-first context in this case. I prepared a branch called 'PerformanceTests' (https://github.com/thomasgalliker/EntityFramework.Toolkit/tree/PerformanceTests) in which I created a test 'PerformanceTests' with the failing bulk insert. (https://github.com/thomasgalliker/EntityFramework.Toolkit/blob/PerformanceTests/%20EntityFramework.Toolkit.Tests/PerformanceTests.cs). The test case is called 'AddEntitiesPerformanceTest_BulkInsert'.

Would be great if you could quickly look at it - but don't waste a bunch of time on it :) If you want me to create a fork from your repo, I can do so too.

Thanks. Thomas

I'll have a look this evening. Thanks for the input!

There seems to be a problem with your context. When you configure Employee and Student who both inherit from Person the DbContext apparently do not create an entity set map for those two entity classes even though they are mapped to tables. My guess is that this has something to do with those two classes inheriting their primary key. Exactly where the mapping of Employee and Student ends up being stored I do not know. I'll investigate more later.

I‘ll have a look at it too. I got to work your code from codeproject with the EntityFramework.Toolkit DbContext. However, there was some change necessary. I will try to get it work with your latest github source.

The point with the inherited classes is clearly my issue. Thanks. Furthermore, I found that it is probably a good idea to put all calls to ExecuteReader() into a using(...) statement so that the readers get disposed after executing. This way I resolved the error „There is already an open DataReader associated with this Command which must be closed first.“

Good idea with the using statements. Fixed that. Thanks!

Hi @mtanneryd, I also thank you for the effort you put into this library.
I have 3 classes as mentioned below. and I get the error 'Sequence contains no matching element' after running the "bulkinsertall" method. Thanks for your help
(I am not very good in english)
```
var ctx = new ApplicationDbContext();
var ins=GetAllInstitution();
var request = new bulkinsertrequest
{
entities = ins,
recursive = false,
allownotnullselfreferences = true
};
ctx.bulkinsertall(request);


public abstract class BaseEntity
{
public BaseEntity()
{
DateCreated = DateTime.Now;
}
public int Id { set; get; }
[Display(Name = "Oluşturma Tarihi")]
public DateTime DateCreated { set; get; }
public virtual bool IsDeleted { get; set; }
}

    [Table("Corporations")]
    public abstract class Corporation : BaseEntity
    {
        [Required(ErrorMessage ="{0} Alan zorunlu")]
        [Display(Name = "Adı")]
        public string Name { get; set; }
        [Required(ErrorMessage = "{0} Alan zorunlu")]
        public int OrganizationId { get; set; }
        [Display(Name = "Şehir")]
        [Required]
        public int CityId { get; set; }
        public City City { get; set; }
        public ICollection<CorporateAgreement> Agreements { set; get; }
        [NotMapped]
        public bool IsExpired
        {
            get
            {
                if (Agreements != null && Agreements.Any(z => !z.IsDeleted))
                {
                    return false;
                }
                return true;
            }
        }
    }

[Table("Institution")]
public class Institution:Corporation
{
public string InstitutionMainType { get; set; }
public string InstitutionConnectedType { get; set; }
public DateTime? ClosedDate { get; set; }
public DateTime? OpenedDate { get; set; }
}