Skip to content

Repository files navigation

BulkExtensions

This project was built as an extension to add bulk operations functionality to the Entity Framework (EF6 and EFCore). It works as extension methods of the DbContext class and is very simple to use. The library uses the same connection your context created and if the context's database have a CurrentTransaction it will use it, otherwise it creates an internal one for the scope of the operation.

It relies on the SqlBulkCopy class to perform all the operations, because of that, it can't handle navigation properties and will not persist relationships between entities, but there is a workaround for that if the foreign keys are being explicitly mapped in your model classes. See the workaround in the examples below.

Overall features

  • Bulk insert, update, insert or update, delete operations;
  • Support context transaction (Uses the same connection and transaction of the context);
  • If the context has no transaction it creates and uses an internal one for safety;
  • Support tables with AutoIncrement key, not auto increment keys and composite keys;
  • Output database generated Ids;
  • Output database computed columns;
  • Support Table-Per-Hierarchy(TPH);

Framework Targets

  • For EF6 you can use it with .NetFramewok 4.5+;
  • For EFCore you can use it with .NetFramewok 4.5.1+ or .NetCore1.0+;

Release notes

You can see the release notes on the Releases page

Installation

You can install it using the nuget package for your EF version:

How to use it

You just need to call the methods bellow for the feature you want to use passing the collection of entities to perform the operation.

context.BulkInsert(entities);context.BulkUpdate(entities);context.BulkInsertOrUpdate(entities);context.BulkDelete(entities);//Generated Ids are populated by adding the optional parammetercontext.BulkInsert(entities,InsertOptions.OutputIdentity);context.BulkInsertOrUpdate(entities,InsertOptions.OutputIdentity);//Computed columns are populated by adding the optional parammetercontext.BulkInsert(entityList,InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//It is possible to combine optionscontext.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);

Examples

Bulk insert

There is two ways of using this method. By only using the list as parameters for this extension method it will perform a standard SqlBulkCopy operation, witch will not return the Ids of the inserted entities because of a limitation of the SqlBulkCopy class.

By also selecting the option 'InsertOptions.OutputIdentity' as the second parameter, the method will fill the generated Ids for the entities inserted(If they are database generated. e.g. auto increment), using temporary tables to output and select the generated Ids under the hood. See the exemples below:

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList);/* But if you want the generated ids you can call the function as below */context.BulkInsert(entityList,InsertOptions.OutputIdentity);entityList.First().Id//Should have the id generated by the database./* The ids generated by the database will be set for every inserted item in the entities collection */

Workaround for relationships

You can explicitly set the foreign keys of your entity and insert it. See the example below.

usingEntityFramework.BulkExtensionsvar role =context.Set<Roles>().Single(entity =>entity.Name=="Admin").ToList();varentityList=newList<User>();entityList.Add(newUser{RoleId=role.Id});//Set the role id on the newly created userentityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});//Bulk insert extension methodcontext.BulkInsert(entityList);/* By explicitly setting the foreing key the relationship will be persisted in the database. */

Bulk update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Bulk update extension methodcontext.BulkUpdate(entityList);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries and then drop the mirror table. The original course of action of  the entity framework would be create an UPDATE command for each entity, wich suffers  a big performance hit with an increased number of entries to update. */

Bulk insert or update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Add some new entities.for(vari=0;i<10;i++){entityList.Add(newMyEntity{Value=rnd.Next(1000);});}//Bulk update extension methodcontext.BulkInsertOrUpdate(entityList);/* Also, if you want the generated ids for the newly added entitites you can use the code below*/context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries, the ones not matched are new and will be inserted, and then drop  the mirror table. The original course of action of the entity framework would be  create an UPDATE command for each entity, wich suffers a big performance hit with  an increased number of entries to update. */

Bulk delete

usingEntityFramework.BulkExtensions//Read some entities from database.var entityList =context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").toList();//Bulk delete extension methodcontext.BulkDelete(entityList);/* This operation will delete all the entities in the list from the database. */

Computed columns

It is possible to output the values of computed columns in the same way the generated Ids are outputed. There is a new option InsertOptions.OutputComputed for the BulkInsert and BulkInsertOrUpdate operations and a new UpdateOptions.OutputComputed option for BulkUpdate. This option can be combined with the InsertOptions.OutputIdentity.

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList,InsertOptions.OutputComputed);//Accessing a computed property will return the generated valuevarfirstComputedValue=entityList.First().MyComputedProperty;/* The computed values generated by the database will be set for every inserted item in the entities collection *///You can also output computed values on BulkInsertOrUpdatecontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);//And you can output computed values on BulkUpdate too.context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//Combination with InsertOptions.OutputIdentity works as well.context.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);//ORcontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);/*This will output the generated indentity and the computed columns.

Transactions

The work with transactions is pretty straightforward and flexible. If you are performing multiple operations on the context using a transaction it is safe to use any bulk operation, the operations use the transaction of the context to perform database manipulation.

usingEntityFramework.BulkExtensions//Begin a transaction on your context.using(vartransaction=context.Database.BeginTransaction()){varrnd=newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation//Commit the transactiontransaction.Commit();}/* The two operations will run on the same transaction, if something goes worng the rollback wouldundo the changes made by the two bulk operations.*/

If you are not using transaction, each bulk operations creates a transaction for the scope of the operation.

usingEntityFramework.BulkExtensionsvar rnd =newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation/* Each operations will run on it's own transaction. For example, if something goes worng with the delete operation the changes made by it would be undone but the changes made by the update before would persist.*/

Credits

This library is based on the SqlBulkTools by Greg Taylor.

About

Bulk operations extension for Entity Framework(EF6 and EFCore).

Resources

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - gorillapower/BulkExtensions: Bulk operations extension for Entity Framework(EF6 and EFCore). · GitHub
Skip to content

Repository files navigation

BulkExtensions

This project was built as an extension to add bulk operations functionality to the Entity Framework (EF6 and EFCore). It works as extension methods of the DbContext class and is very simple to use. The library uses the same connection your context created and if the context's database have a CurrentTransaction it will use it, otherwise it creates an internal one for the scope of the operation.

It relies on the SqlBulkCopy class to perform all the operations, because of that, it can't handle navigation properties and will not persist relationships between entities, but there is a workaround for that if the foreign keys are being explicitly mapped in your model classes. See the workaround in the examples below.

Overall features

  • Bulk insert, update, insert or update, delete operations;
  • Support context transaction (Uses the same connection and transaction of the context);
  • If the context has no transaction it creates and uses an internal one for safety;
  • Support tables with AutoIncrement key, not auto increment keys and composite keys;
  • Output database generated Ids;
  • Output database computed columns;
  • Support Table-Per-Hierarchy(TPH);

Framework Targets

  • For EF6 you can use it with .NetFramewok 4.5+;
  • For EFCore you can use it with .NetFramewok 4.5.1+ or .NetCore1.0+;

Release notes

You can see the release notes on the Releases page

Installation

You can install it using the nuget package for your EF version:

How to use it

You just need to call the methods bellow for the feature you want to use passing the collection of entities to perform the operation.

context.BulkInsert(entities);context.BulkUpdate(entities);context.BulkInsertOrUpdate(entities);context.BulkDelete(entities);//Generated Ids are populated by adding the optional parammetercontext.BulkInsert(entities,InsertOptions.OutputIdentity);context.BulkInsertOrUpdate(entities,InsertOptions.OutputIdentity);//Computed columns are populated by adding the optional parammetercontext.BulkInsert(entityList,InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//It is possible to combine optionscontext.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);

Examples

Bulk insert

There is two ways of using this method. By only using the list as parameters for this extension method it will perform a standard SqlBulkCopy operation, witch will not return the Ids of the inserted entities because of a limitation of the SqlBulkCopy class.

By also selecting the option 'InsertOptions.OutputIdentity' as the second parameter, the method will fill the generated Ids for the entities inserted(If they are database generated. e.g. auto increment), using temporary tables to output and select the generated Ids under the hood. See the exemples below:

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList);/* But if you want the generated ids you can call the function as below */context.BulkInsert(entityList,InsertOptions.OutputIdentity);entityList.First().Id//Should have the id generated by the database./* The ids generated by the database will be set for every inserted item in the entities collection */

Workaround for relationships

You can explicitly set the foreign keys of your entity and insert it. See the example below.

usingEntityFramework.BulkExtensionsvar role =context.Set<Roles>().Single(entity =>entity.Name=="Admin").ToList();varentityList=newList<User>();entityList.Add(newUser{RoleId=role.Id});//Set the role id on the newly created userentityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});//Bulk insert extension methodcontext.BulkInsert(entityList);/* By explicitly setting the foreing key the relationship will be persisted in the database. */

Bulk update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Bulk update extension methodcontext.BulkUpdate(entityList);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries and then drop the mirror table. The original course of action of  the entity framework would be create an UPDATE command for each entity, wich suffers  a big performance hit with an increased number of entries to update. */

Bulk insert or update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Add some new entities.for(vari=0;i<10;i++){entityList.Add(newMyEntity{Value=rnd.Next(1000);});}//Bulk update extension methodcontext.BulkInsertOrUpdate(entityList);/* Also, if you want the generated ids for the newly added entitites you can use the code below*/context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries, the ones not matched are new and will be inserted, and then drop  the mirror table. The original course of action of the entity framework would be  create an UPDATE command for each entity, wich suffers a big performance hit with  an increased number of entries to update. */

Bulk delete

usingEntityFramework.BulkExtensions//Read some entities from database.var entityList =context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").toList();//Bulk delete extension methodcontext.BulkDelete(entityList);/* This operation will delete all the entities in the list from the database. */

Computed columns

It is possible to output the values of computed columns in the same way the generated Ids are outputed. There is a new option InsertOptions.OutputComputed for the BulkInsert and BulkInsertOrUpdate operations and a new UpdateOptions.OutputComputed option for BulkUpdate. This option can be combined with the InsertOptions.OutputIdentity.

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList,InsertOptions.OutputComputed);//Accessing a computed property will return the generated valuevarfirstComputedValue=entityList.First().MyComputedProperty;/* The computed values generated by the database will be set for every inserted item in the entities collection *///You can also output computed values on BulkInsertOrUpdatecontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);//And you can output computed values on BulkUpdate too.context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//Combination with InsertOptions.OutputIdentity works as well.context.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);//ORcontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);/*This will output the generated indentity and the computed columns.

Transactions

The work with transactions is pretty straightforward and flexible. If you are performing multiple operations on the context using a transaction it is safe to use any bulk operation, the operations use the transaction of the context to perform database manipulation.

usingEntityFramework.BulkExtensions//Begin a transaction on your context.using(vartransaction=context.Database.BeginTransaction()){varrnd=newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation//Commit the transactiontransaction.Commit();}/* The two operations will run on the same transaction, if something goes worng the rollback wouldundo the changes made by the two bulk operations.*/

If you are not using transaction, each bulk operations creates a transaction for the scope of the operation.

usingEntityFramework.BulkExtensionsvar rnd =newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation/* Each operations will run on it's own transaction. For example, if something goes worng with the delete operation the changes made by it would be undone but the changes made by the update before would persist.*/

Credits

This library is based on the SqlBulkTools by Greg Taylor.

About

Bulk operations extension for Entity Framework(EF6 and EFCore).

Resources

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - gorillapower/BulkExtensions: Bulk operations extension for Entity Framework(EF6 and EFCore). · GitHub
Skip to content

Repository files navigation

BulkExtensions

This project was built as an extension to add bulk operations functionality to the Entity Framework (EF6 and EFCore). It works as extension methods of the DbContext class and is very simple to use. The library uses the same connection your context created and if the context's database have a CurrentTransaction it will use it, otherwise it creates an internal one for the scope of the operation.

It relies on the SqlBulkCopy class to perform all the operations, because of that, it can't handle navigation properties and will not persist relationships between entities, but there is a workaround for that if the foreign keys are being explicitly mapped in your model classes. See the workaround in the examples below.

Overall features

  • Bulk insert, update, insert or update, delete operations;
  • Support context transaction (Uses the same connection and transaction of the context);
  • If the context has no transaction it creates and uses an internal one for safety;
  • Support tables with AutoIncrement key, not auto increment keys and composite keys;
  • Output database generated Ids;
  • Output database computed columns;
  • Support Table-Per-Hierarchy(TPH);

Framework Targets

  • For EF6 you can use it with .NetFramewok 4.5+;
  • For EFCore you can use it with .NetFramewok 4.5.1+ or .NetCore1.0+;

Release notes

You can see the release notes on the Releases page

Installation

You can install it using the nuget package for your EF version:

How to use it

You just need to call the methods bellow for the feature you want to use passing the collection of entities to perform the operation.

context.BulkInsert(entities);context.BulkUpdate(entities);context.BulkInsertOrUpdate(entities);context.BulkDelete(entities);//Generated Ids are populated by adding the optional parammetercontext.BulkInsert(entities,InsertOptions.OutputIdentity);context.BulkInsertOrUpdate(entities,InsertOptions.OutputIdentity);//Computed columns are populated by adding the optional parammetercontext.BulkInsert(entityList,InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//It is possible to combine optionscontext.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);

Examples

Bulk insert

There is two ways of using this method. By only using the list as parameters for this extension method it will perform a standard SqlBulkCopy operation, witch will not return the Ids of the inserted entities because of a limitation of the SqlBulkCopy class.

By also selecting the option 'InsertOptions.OutputIdentity' as the second parameter, the method will fill the generated Ids for the entities inserted(If they are database generated. e.g. auto increment), using temporary tables to output and select the generated Ids under the hood. See the exemples below:

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList);/* But if you want the generated ids you can call the function as below */context.BulkInsert(entityList,InsertOptions.OutputIdentity);entityList.First().Id//Should have the id generated by the database./* The ids generated by the database will be set for every inserted item in the entities collection */

Workaround for relationships

You can explicitly set the foreign keys of your entity and insert it. See the example below.

usingEntityFramework.BulkExtensionsvar role =context.Set<Roles>().Single(entity =>entity.Name=="Admin").ToList();varentityList=newList<User>();entityList.Add(newUser{RoleId=role.Id});//Set the role id on the newly created userentityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});//Bulk insert extension methodcontext.BulkInsert(entityList);/* By explicitly setting the foreing key the relationship will be persisted in the database. */

Bulk update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Bulk update extension methodcontext.BulkUpdate(entityList);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries and then drop the mirror table. The original course of action of  the entity framework would be create an UPDATE command for each entity, wich suffers  a big performance hit with an increased number of entries to update. */

Bulk insert or update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Add some new entities.for(vari=0;i<10;i++){entityList.Add(newMyEntity{Value=rnd.Next(1000);});}//Bulk update extension methodcontext.BulkInsertOrUpdate(entityList);/* Also, if you want the generated ids for the newly added entitites you can use the code below*/context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries, the ones not matched are new and will be inserted, and then drop  the mirror table. The original course of action of the entity framework would be  create an UPDATE command for each entity, wich suffers a big performance hit with  an increased number of entries to update. */

Bulk delete

usingEntityFramework.BulkExtensions//Read some entities from database.var entityList =context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").toList();//Bulk delete extension methodcontext.BulkDelete(entityList);/* This operation will delete all the entities in the list from the database. */

Computed columns

It is possible to output the values of computed columns in the same way the generated Ids are outputed. There is a new option InsertOptions.OutputComputed for the BulkInsert and BulkInsertOrUpdate operations and a new UpdateOptions.OutputComputed option for BulkUpdate. This option can be combined with the InsertOptions.OutputIdentity.

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList,InsertOptions.OutputComputed);//Accessing a computed property will return the generated valuevarfirstComputedValue=entityList.First().MyComputedProperty;/* The computed values generated by the database will be set for every inserted item in the entities collection *///You can also output computed values on BulkInsertOrUpdatecontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);//And you can output computed values on BulkUpdate too.context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//Combination with InsertOptions.OutputIdentity works as well.context.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);//ORcontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);/*This will output the generated indentity and the computed columns.

Transactions

The work with transactions is pretty straightforward and flexible. If you are performing multiple operations on the context using a transaction it is safe to use any bulk operation, the operations use the transaction of the context to perform database manipulation.

usingEntityFramework.BulkExtensions//Begin a transaction on your context.using(vartransaction=context.Database.BeginTransaction()){varrnd=newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation//Commit the transactiontransaction.Commit();}/* The two operations will run on the same transaction, if something goes worng the rollback wouldundo the changes made by the two bulk operations.*/

If you are not using transaction, each bulk operations creates a transaction for the scope of the operation.

usingEntityFramework.BulkExtensionsvar rnd =newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation/* Each operations will run on it's own transaction. For example, if something goes worng with the delete operation the changes made by it would be undone but the changes made by the update before would persist.*/

Credits

This library is based on the SqlBulkTools by Greg Taylor.

About

Bulk operations extension for Entity Framework(EF6 and EFCore).

Resources

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - gorillapower/BulkExtensions: Bulk operations extension for Entity Framework(EF6 and EFCore). · GitHub
Skip to content

Repository files navigation

BulkExtensions

This project was built as an extension to add bulk operations functionality to the Entity Framework (EF6 and EFCore). It works as extension methods of the DbContext class and is very simple to use. The library uses the same connection your context created and if the context's database have a CurrentTransaction it will use it, otherwise it creates an internal one for the scope of the operation.

It relies on the SqlBulkCopy class to perform all the operations, because of that, it can't handle navigation properties and will not persist relationships between entities, but there is a workaround for that if the foreign keys are being explicitly mapped in your model classes. See the workaround in the examples below.

Overall features

  • Bulk insert, update, insert or update, delete operations;
  • Support context transaction (Uses the same connection and transaction of the context);
  • If the context has no transaction it creates and uses an internal one for safety;
  • Support tables with AutoIncrement key, not auto increment keys and composite keys;
  • Output database generated Ids;
  • Output database computed columns;
  • Support Table-Per-Hierarchy(TPH);

Framework Targets

  • For EF6 you can use it with .NetFramewok 4.5+;
  • For EFCore you can use it with .NetFramewok 4.5.1+ or .NetCore1.0+;

Release notes

You can see the release notes on the Releases page

Installation

You can install it using the nuget package for your EF version:

How to use it

You just need to call the methods bellow for the feature you want to use passing the collection of entities to perform the operation.

context.BulkInsert(entities);context.BulkUpdate(entities);context.BulkInsertOrUpdate(entities);context.BulkDelete(entities);//Generated Ids are populated by adding the optional parammetercontext.BulkInsert(entities,InsertOptions.OutputIdentity);context.BulkInsertOrUpdate(entities,InsertOptions.OutputIdentity);//Computed columns are populated by adding the optional parammetercontext.BulkInsert(entityList,InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//It is possible to combine optionscontext.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);

Examples

Bulk insert

There is two ways of using this method. By only using the list as parameters for this extension method it will perform a standard SqlBulkCopy operation, witch will not return the Ids of the inserted entities because of a limitation of the SqlBulkCopy class.

By also selecting the option 'InsertOptions.OutputIdentity' as the second parameter, the method will fill the generated Ids for the entities inserted(If they are database generated. e.g. auto increment), using temporary tables to output and select the generated Ids under the hood. See the exemples below:

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList);/* But if you want the generated ids you can call the function as below */context.BulkInsert(entityList,InsertOptions.OutputIdentity);entityList.First().Id//Should have the id generated by the database./* The ids generated by the database will be set for every inserted item in the entities collection */

Workaround for relationships

You can explicitly set the foreign keys of your entity and insert it. See the example below.

usingEntityFramework.BulkExtensionsvar role =context.Set<Roles>().Single(entity =>entity.Name=="Admin").ToList();varentityList=newList<User>();entityList.Add(newUser{RoleId=role.Id});//Set the role id on the newly created userentityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});//Bulk insert extension methodcontext.BulkInsert(entityList);/* By explicitly setting the foreing key the relationship will be persisted in the database. */

Bulk update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Bulk update extension methodcontext.BulkUpdate(entityList);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries and then drop the mirror table. The original course of action of  the entity framework would be create an UPDATE command for each entity, wich suffers  a big performance hit with an increased number of entries to update. */

Bulk insert or update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Add some new entities.for(vari=0;i<10;i++){entityList.Add(newMyEntity{Value=rnd.Next(1000);});}//Bulk update extension methodcontext.BulkInsertOrUpdate(entityList);/* Also, if you want the generated ids for the newly added entitites you can use the code below*/context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries, the ones not matched are new and will be inserted, and then drop  the mirror table. The original course of action of the entity framework would be  create an UPDATE command for each entity, wich suffers a big performance hit with  an increased number of entries to update. */

Bulk delete

usingEntityFramework.BulkExtensions//Read some entities from database.var entityList =context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").toList();//Bulk delete extension methodcontext.BulkDelete(entityList);/* This operation will delete all the entities in the list from the database. */

Computed columns

It is possible to output the values of computed columns in the same way the generated Ids are outputed. There is a new option InsertOptions.OutputComputed for the BulkInsert and BulkInsertOrUpdate operations and a new UpdateOptions.OutputComputed option for BulkUpdate. This option can be combined with the InsertOptions.OutputIdentity.

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList,InsertOptions.OutputComputed);//Accessing a computed property will return the generated valuevarfirstComputedValue=entityList.First().MyComputedProperty;/* The computed values generated by the database will be set for every inserted item in the entities collection *///You can also output computed values on BulkInsertOrUpdatecontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);//And you can output computed values on BulkUpdate too.context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//Combination with InsertOptions.OutputIdentity works as well.context.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);//ORcontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);/*This will output the generated indentity and the computed columns.

Transactions

The work with transactions is pretty straightforward and flexible. If you are performing multiple operations on the context using a transaction it is safe to use any bulk operation, the operations use the transaction of the context to perform database manipulation.

usingEntityFramework.BulkExtensions//Begin a transaction on your context.using(vartransaction=context.Database.BeginTransaction()){varrnd=newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation//Commit the transactiontransaction.Commit();}/* The two operations will run on the same transaction, if something goes worng the rollback wouldundo the changes made by the two bulk operations.*/

If you are not using transaction, each bulk operations creates a transaction for the scope of the operation.

usingEntityFramework.BulkExtensionsvar rnd =newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation/* Each operations will run on it's own transaction. For example, if something goes worng with the delete operation the changes made by it would be undone but the changes made by the update before would persist.*/

Credits

This library is based on the SqlBulkTools by Greg Taylor.

About

Bulk operations extension for Entity Framework(EF6 and EFCore).

Resources

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - gorillapower/BulkExtensions: Bulk operations extension for Entity Framework(EF6 and EFCore). · GitHub
Skip to content

Repository files navigation

BulkExtensions

This project was built as an extension to add bulk operations functionality to the Entity Framework (EF6 and EFCore). It works as extension methods of the DbContext class and is very simple to use. The library uses the same connection your context created and if the context's database have a CurrentTransaction it will use it, otherwise it creates an internal one for the scope of the operation.

It relies on the SqlBulkCopy class to perform all the operations, because of that, it can't handle navigation properties and will not persist relationships between entities, but there is a workaround for that if the foreign keys are being explicitly mapped in your model classes. See the workaround in the examples below.

Overall features

  • Bulk insert, update, insert or update, delete operations;
  • Support context transaction (Uses the same connection and transaction of the context);
  • If the context has no transaction it creates and uses an internal one for safety;
  • Support tables with AutoIncrement key, not auto increment keys and composite keys;
  • Output database generated Ids;
  • Output database computed columns;
  • Support Table-Per-Hierarchy(TPH);

Framework Targets

  • For EF6 you can use it with .NetFramewok 4.5+;
  • For EFCore you can use it with .NetFramewok 4.5.1+ or .NetCore1.0+;

Release notes

You can see the release notes on the Releases page

Installation

You can install it using the nuget package for your EF version:

How to use it

You just need to call the methods bellow for the feature you want to use passing the collection of entities to perform the operation.

context.BulkInsert(entities);context.BulkUpdate(entities);context.BulkInsertOrUpdate(entities);context.BulkDelete(entities);//Generated Ids are populated by adding the optional parammetercontext.BulkInsert(entities,InsertOptions.OutputIdentity);context.BulkInsertOrUpdate(entities,InsertOptions.OutputIdentity);//Computed columns are populated by adding the optional parammetercontext.BulkInsert(entityList,InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//It is possible to combine optionscontext.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);

Examples

Bulk insert

There is two ways of using this method. By only using the list as parameters for this extension method it will perform a standard SqlBulkCopy operation, witch will not return the Ids of the inserted entities because of a limitation of the SqlBulkCopy class.

By also selecting the option 'InsertOptions.OutputIdentity' as the second parameter, the method will fill the generated Ids for the entities inserted(If they are database generated. e.g. auto increment), using temporary tables to output and select the generated Ids under the hood. See the exemples below:

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList);/* But if you want the generated ids you can call the function as below */context.BulkInsert(entityList,InsertOptions.OutputIdentity);entityList.First().Id//Should have the id generated by the database./* The ids generated by the database will be set for every inserted item in the entities collection */

Workaround for relationships

You can explicitly set the foreign keys of your entity and insert it. See the example below.

usingEntityFramework.BulkExtensionsvar role =context.Set<Roles>().Single(entity =>entity.Name=="Admin").ToList();varentityList=newList<User>();entityList.Add(newUser{RoleId=role.Id});//Set the role id on the newly created userentityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});//Bulk insert extension methodcontext.BulkInsert(entityList);/* By explicitly setting the foreing key the relationship will be persisted in the database. */

Bulk update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Bulk update extension methodcontext.BulkUpdate(entityList);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries and then drop the mirror table. The original course of action of  the entity framework would be create an UPDATE command for each entity, wich suffers  a big performance hit with an increased number of entries to update. */

Bulk insert or update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Add some new entities.for(vari=0;i<10;i++){entityList.Add(newMyEntity{Value=rnd.Next(1000);});}//Bulk update extension methodcontext.BulkInsertOrUpdate(entityList);/* Also, if you want the generated ids for the newly added entitites you can use the code below*/context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries, the ones not matched are new and will be inserted, and then drop  the mirror table. The original course of action of the entity framework would be  create an UPDATE command for each entity, wich suffers a big performance hit with  an increased number of entries to update. */

Bulk delete

usingEntityFramework.BulkExtensions//Read some entities from database.var entityList =context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").toList();//Bulk delete extension methodcontext.BulkDelete(entityList);/* This operation will delete all the entities in the list from the database. */

Computed columns

It is possible to output the values of computed columns in the same way the generated Ids are outputed. There is a new option InsertOptions.OutputComputed for the BulkInsert and BulkInsertOrUpdate operations and a new UpdateOptions.OutputComputed option for BulkUpdate. This option can be combined with the InsertOptions.OutputIdentity.

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList,InsertOptions.OutputComputed);//Accessing a computed property will return the generated valuevarfirstComputedValue=entityList.First().MyComputedProperty;/* The computed values generated by the database will be set for every inserted item in the entities collection *///You can also output computed values on BulkInsertOrUpdatecontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);//And you can output computed values on BulkUpdate too.context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//Combination with InsertOptions.OutputIdentity works as well.context.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);//ORcontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);/*This will output the generated indentity and the computed columns.

Transactions

The work with transactions is pretty straightforward and flexible. If you are performing multiple operations on the context using a transaction it is safe to use any bulk operation, the operations use the transaction of the context to perform database manipulation.

usingEntityFramework.BulkExtensions//Begin a transaction on your context.using(vartransaction=context.Database.BeginTransaction()){varrnd=newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation//Commit the transactiontransaction.Commit();}/* The two operations will run on the same transaction, if something goes worng the rollback wouldundo the changes made by the two bulk operations.*/

If you are not using transaction, each bulk operations creates a transaction for the scope of the operation.

usingEntityFramework.BulkExtensionsvar rnd =newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation/* Each operations will run on it's own transaction. For example, if something goes worng with the delete operation the changes made by it would be undone but the changes made by the update before would persist.*/

Credits

This library is based on the SqlBulkTools by Greg Taylor.

About

Bulk operations extension for Entity Framework(EF6 and EFCore).

Resources

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - gorillapower/BulkExtensions: Bulk operations extension for Entity Framework(EF6 and EFCore). · GitHub
Skip to content

Repository files navigation

BulkExtensions

This project was built as an extension to add bulk operations functionality to the Entity Framework (EF6 and EFCore). It works as extension methods of the DbContext class and is very simple to use. The library uses the same connection your context created and if the context's database have a CurrentTransaction it will use it, otherwise it creates an internal one for the scope of the operation.

It relies on the SqlBulkCopy class to perform all the operations, because of that, it can't handle navigation properties and will not persist relationships between entities, but there is a workaround for that if the foreign keys are being explicitly mapped in your model classes. See the workaround in the examples below.

Overall features

  • Bulk insert, update, insert or update, delete operations;
  • Support context transaction (Uses the same connection and transaction of the context);
  • If the context has no transaction it creates and uses an internal one for safety;
  • Support tables with AutoIncrement key, not auto increment keys and composite keys;
  • Output database generated Ids;
  • Output database computed columns;
  • Support Table-Per-Hierarchy(TPH);

Framework Targets

  • For EF6 you can use it with .NetFramewok 4.5+;
  • For EFCore you can use it with .NetFramewok 4.5.1+ or .NetCore1.0+;

Release notes

You can see the release notes on the Releases page

Installation

You can install it using the nuget package for your EF version:

How to use it

You just need to call the methods bellow for the feature you want to use passing the collection of entities to perform the operation.

context.BulkInsert(entities);context.BulkUpdate(entities);context.BulkInsertOrUpdate(entities);context.BulkDelete(entities);//Generated Ids are populated by adding the optional parammetercontext.BulkInsert(entities,InsertOptions.OutputIdentity);context.BulkInsertOrUpdate(entities,InsertOptions.OutputIdentity);//Computed columns are populated by adding the optional parammetercontext.BulkInsert(entityList,InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//It is possible to combine optionscontext.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);

Examples

Bulk insert

There is two ways of using this method. By only using the list as parameters for this extension method it will perform a standard SqlBulkCopy operation, witch will not return the Ids of the inserted entities because of a limitation of the SqlBulkCopy class.

By also selecting the option 'InsertOptions.OutputIdentity' as the second parameter, the method will fill the generated Ids for the entities inserted(If they are database generated. e.g. auto increment), using temporary tables to output and select the generated Ids under the hood. See the exemples below:

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList);/* But if you want the generated ids you can call the function as below */context.BulkInsert(entityList,InsertOptions.OutputIdentity);entityList.First().Id//Should have the id generated by the database./* The ids generated by the database will be set for every inserted item in the entities collection */

Workaround for relationships

You can explicitly set the foreign keys of your entity and insert it. See the example below.

usingEntityFramework.BulkExtensionsvar role =context.Set<Roles>().Single(entity =>entity.Name=="Admin").ToList();varentityList=newList<User>();entityList.Add(newUser{RoleId=role.Id});//Set the role id on the newly created userentityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});//Bulk insert extension methodcontext.BulkInsert(entityList);/* By explicitly setting the foreing key the relationship will be persisted in the database. */

Bulk update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Bulk update extension methodcontext.BulkUpdate(entityList);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries and then drop the mirror table. The original course of action of  the entity framework would be create an UPDATE command for each entity, wich suffers  a big performance hit with an increased number of entries to update. */

Bulk insert or update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Add some new entities.for(vari=0;i<10;i++){entityList.Add(newMyEntity{Value=rnd.Next(1000);});}//Bulk update extension methodcontext.BulkInsertOrUpdate(entityList);/* Also, if you want the generated ids for the newly added entitites you can use the code below*/context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries, the ones not matched are new and will be inserted, and then drop  the mirror table. The original course of action of the entity framework would be  create an UPDATE command for each entity, wich suffers a big performance hit with  an increased number of entries to update. */

Bulk delete

usingEntityFramework.BulkExtensions//Read some entities from database.var entityList =context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").toList();//Bulk delete extension methodcontext.BulkDelete(entityList);/* This operation will delete all the entities in the list from the database. */

Computed columns

It is possible to output the values of computed columns in the same way the generated Ids are outputed. There is a new option InsertOptions.OutputComputed for the BulkInsert and BulkInsertOrUpdate operations and a new UpdateOptions.OutputComputed option for BulkUpdate. This option can be combined with the InsertOptions.OutputIdentity.

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList,InsertOptions.OutputComputed);//Accessing a computed property will return the generated valuevarfirstComputedValue=entityList.First().MyComputedProperty;/* The computed values generated by the database will be set for every inserted item in the entities collection *///You can also output computed values on BulkInsertOrUpdatecontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);//And you can output computed values on BulkUpdate too.context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//Combination with InsertOptions.OutputIdentity works as well.context.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);//ORcontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);/*This will output the generated indentity and the computed columns.

Transactions

The work with transactions is pretty straightforward and flexible. If you are performing multiple operations on the context using a transaction it is safe to use any bulk operation, the operations use the transaction of the context to perform database manipulation.

usingEntityFramework.BulkExtensions//Begin a transaction on your context.using(vartransaction=context.Database.BeginTransaction()){varrnd=newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation//Commit the transactiontransaction.Commit();}/* The two operations will run on the same transaction, if something goes worng the rollback wouldundo the changes made by the two bulk operations.*/

If you are not using transaction, each bulk operations creates a transaction for the scope of the operation.

usingEntityFramework.BulkExtensionsvar rnd =newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation/* Each operations will run on it's own transaction. For example, if something goes worng with the delete operation the changes made by it would be undone but the changes made by the update before would persist.*/

Credits

This library is based on the SqlBulkTools by Greg Taylor.

About

Bulk operations extension for Entity Framework(EF6 and EFCore).

Resources

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - gorillapower/BulkExtensions: Bulk operations extension for Entity Framework(EF6 and EFCore). · GitHub
Skip to content

Repository files navigation

BulkExtensions

This project was built as an extension to add bulk operations functionality to the Entity Framework (EF6 and EFCore). It works as extension methods of the DbContext class and is very simple to use. The library uses the same connection your context created and if the context's database have a CurrentTransaction it will use it, otherwise it creates an internal one for the scope of the operation.

It relies on the SqlBulkCopy class to perform all the operations, because of that, it can't handle navigation properties and will not persist relationships between entities, but there is a workaround for that if the foreign keys are being explicitly mapped in your model classes. See the workaround in the examples below.

Overall features

  • Bulk insert, update, insert or update, delete operations;
  • Support context transaction (Uses the same connection and transaction of the context);
  • If the context has no transaction it creates and uses an internal one for safety;
  • Support tables with AutoIncrement key, not auto increment keys and composite keys;
  • Output database generated Ids;
  • Output database computed columns;
  • Support Table-Per-Hierarchy(TPH);

Framework Targets

  • For EF6 you can use it with .NetFramewok 4.5+;
  • For EFCore you can use it with .NetFramewok 4.5.1+ or .NetCore1.0+;

Release notes

You can see the release notes on the Releases page

Installation

You can install it using the nuget package for your EF version:

How to use it

You just need to call the methods bellow for the feature you want to use passing the collection of entities to perform the operation.

context.BulkInsert(entities);context.BulkUpdate(entities);context.BulkInsertOrUpdate(entities);context.BulkDelete(entities);//Generated Ids are populated by adding the optional parammetercontext.BulkInsert(entities,InsertOptions.OutputIdentity);context.BulkInsertOrUpdate(entities,InsertOptions.OutputIdentity);//Computed columns are populated by adding the optional parammetercontext.BulkInsert(entityList,InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//It is possible to combine optionscontext.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);

Examples

Bulk insert

There is two ways of using this method. By only using the list as parameters for this extension method it will perform a standard SqlBulkCopy operation, witch will not return the Ids of the inserted entities because of a limitation of the SqlBulkCopy class.

By also selecting the option 'InsertOptions.OutputIdentity' as the second parameter, the method will fill the generated Ids for the entities inserted(If they are database generated. e.g. auto increment), using temporary tables to output and select the generated Ids under the hood. See the exemples below:

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList);/* But if you want the generated ids you can call the function as below */context.BulkInsert(entityList,InsertOptions.OutputIdentity);entityList.First().Id//Should have the id generated by the database./* The ids generated by the database will be set for every inserted item in the entities collection */

Workaround for relationships

You can explicitly set the foreign keys of your entity and insert it. See the example below.

usingEntityFramework.BulkExtensionsvar role =context.Set<Roles>().Single(entity =>entity.Name=="Admin").ToList();varentityList=newList<User>();entityList.Add(newUser{RoleId=role.Id});//Set the role id on the newly created userentityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});entityList.Add(newUser{RoleId=role.Id});//Bulk insert extension methodcontext.BulkInsert(entityList);/* By explicitly setting the foreing key the relationship will be persisted in the database. */

Bulk update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Bulk update extension methodcontext.BulkUpdate(entityList);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries and then drop the mirror table. The original course of action of  the entity framework would be create an UPDATE command for each entity, wich suffers  a big performance hit with an increased number of entries to update. */

Bulk insert or update

usingEntityFramework.BulkExtensionsRandom rnd =newRandom();//Read some entities from database.varentityList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinentityList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);}//Add some new entities.for(vari=0;i<10;i++){entityList.Add(newMyEntity{Value=rnd.Next(1000);});}//Bulk update extension methodcontext.BulkInsertOrUpdate(entityList);/* Also, if you want the generated ids for the newly added entitites you can use the code below*/context.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity);/* Under the hood, this operation will create a mirror table of your entity's table,  bulk insert the updated entities using the SqlBulkCopy class, use the MERGE sql  command to transfer the data to the original entity table using the primary keys  to match entries, the ones not matched are new and will be inserted, and then drop  the mirror table. The original course of action of the entity framework would be  create an UPDATE command for each entity, wich suffers a big performance hit with  an increased number of entries to update. */

Bulk delete

usingEntityFramework.BulkExtensions//Read some entities from database.var entityList =context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").toList();//Bulk delete extension methodcontext.BulkDelete(entityList);/* This operation will delete all the entities in the list from the database. */

Computed columns

It is possible to output the values of computed columns in the same way the generated Ids are outputed. There is a new option InsertOptions.OutputComputed for the BulkInsert and BulkInsertOrUpdate operations and a new UpdateOptions.OutputComputed option for BulkUpdate. This option can be combined with the InsertOptions.OutputIdentity.

usingEntityFramework.BulkExtensionsvar entityList =newList<MyEntity>();entityList.Add(newMyEntity());entityList.Add(newMyEntity());entityList.Add(newMyEntity());//Bulk insert extension methodcontext.BulkInsert(entityList,InsertOptions.OutputComputed);//Accessing a computed property will return the generated valuevarfirstComputedValue=entityList.First().MyComputedProperty;/* The computed values generated by the database will be set for every inserted item in the entities collection *///You can also output computed values on BulkInsertOrUpdatecontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputComputed);//And you can output computed values on BulkUpdate too.context.BulkUpdate(entityList,UpdateOptions.OutputComputed);//Combination with InsertOptions.OutputIdentity works as well.context.BulkInsert(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);//ORcontext.BulkInsertOrUpdate(entityList,InsertOptions.OutputIdentity|InsertOptions.OutputComputed);/*This will output the generated indentity and the computed columns.

Transactions

The work with transactions is pretty straightforward and flexible. If you are performing multiple operations on the context using a transaction it is safe to use any bulk operation, the operations use the transaction of the context to perform database manipulation.

usingEntityFramework.BulkExtensions//Begin a transaction on your context.using(vartransaction=context.Database.BeginTransaction()){varrnd=newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation//Commit the transactiontransaction.Commit();}/* The two operations will run on the same transaction, if something goes worng the rollback wouldundo the changes made by the two bulk operations.*/

If you are not using transaction, each bulk operations creates a transaction for the scope of the operation.

usingEntityFramework.BulkExtensionsvar rnd =newRandom();//Read some entities from database.varupdateList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Steve").ToList();foreach(varentityinupdateList){//Replace the old value with some random new value.entity.Value=rnd.Next(1000);entity.OtherProperty="some random string";}//Bulk update extension methodcontext.BulkUpdate(updateList);// 1st operation//Read other entities from database.vardeleteList=context.Set<MyEntity>().Where(entity =>entity.Owner=="Bob").toList();//Bulk delete extension methodcontext.BulkDelete(deleteList);// 2nd operation/* Each operations will run on it's own transaction. For example, if something goes worng with the delete operation the changes made by it would be undone but the changes made by the update before would persist.*/

Credits

This library is based on the SqlBulkTools by Greg Taylor.

About

Bulk operations extension for Entity Framework(EF6 and EFCore).

Resources

Stars

10 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages