Skip to content

Instantly share code, notes, and snippets.

@Thorium
Last active August 29, 2015 14:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Thorium/6782861448d160dd9588 to your computer and use it in GitHub Desktop.
Save Thorium/6782861448d160dd9588 to your computer and use it in GitHub Desktop.
This is EntityFramework.BulkInsert provider for Devart Oracle. Basic idea from this sample: https://efbulkinsert.codeplex.com/discussions/554646 Tested with Devart 8.1, but may have some DTC-OralceLoader-Open()-problems with 8.4.
// Usage:
// 1) Reference Devart.Data.dll and Devart.Data.Oracle.dll
// 2) Register in EF-context constructor:
// this.RegisterDevartBulkInsertProvider();
// 3) Ensure that your entities have [Column("...")] -attributes to map the entity properties to database columns.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Devart.Data.Oracle;
using EntityFramework.BulkInsert.Extensions;
using EntityFramework.BulkInsert.Helpers;
using System.ComponentModel.DataAnnotations.Schema;
namespace EntityFramework.BulkInsert.Providers
{
/// <summary>
/// Devart provider for EntityFramework Bulk Insert.
/// </summary>
public class DevartProvider : ProviderBase<OracleConnection, OracleTransaction>
{
public DevartProvider() : base()
{
}
public override object GetSqlGeography(string wkt, int srid)
{
throw new NotImplementedException();
}
protected override OracleConnection CreateConnection()
{
return new OracleConnection(base.ConnectionString);
}
public override void Run<T>(IEnumerable<T> entities, BulkInsertOptions options)
{
Run(entities, null, options);
}
public override void Run<T>(IEnumerable<T> entities, OracleTransaction transaction, BulkInsertOptions options)
{
if (!entities.Any()) return;
var conn = transaction != null ? transaction.Connection : (OracleConnection) base.DbConnection;
var openedConnection = false;
if (conn.State == System.Data.ConnectionState.Closed)
{
conn.Open();
openedConnection = true;
}
var list = entities.ToArray();
var props = list[0].GetType().GetProperties();
var dbnames = props.Select(p => Tuple.Create(
p,
(System.ComponentModel.DataAnnotations.Schema.ColumnAttribute)
p.GetCustomAttributes(typeof (ColumnAttribute), true).FirstOrDefault()
)).Where(a => a.Item2 != null).ToArray();
try
{
string tablename;
var table = typeof(T).GetCustomAttributes(typeof(TableAttribute), true).FirstOrDefault() as TableAttribute;
if (table != null)
{
tablename = table.Name;
}
else
{
using (var reader = new MappedDataReader<T>(list, this))
{
tablename = reader.TableName;
}
}
using (var loader = new OracleLoader(tablename, conn))
{
//loader.BufferSize = options.BatchSize;
loader.CreateColumns();
loader.Open();
var columns = loader.Columns.OfType<OracleLoaderColumn>().Select(a => a.Name).ToArray();
foreach (var t in list)
{
foreach (var prop in dbnames.Where(x => columns.Contains(x.Item2.Name)))
{
loader.SetValue(prop.Item2.Name, prop.Item1.GetValue(t));
}
loader.NextRow();
}
}
}
finally
{
if (openedConnection)
{
conn.Close();
}
}
}
}
}
namespace System.Data.Entity {
public static class EntityFrameworkContextExtensions
{
public static void RegisterDevartBulkInsertProvider(this DbContext context)
{
if ( /* your way to detect if Oracle is in use, e.g. ConfigurationManager.AppSettings */) return;
try
{
EntityFramework.BulkInsert.ProviderFactory.Get(context);
}
catch (EntityFramework.BulkInsert.Exceptions.BulkInsertProviderNotFoundException)
{
EntityFramework.BulkInsert.ProviderFactory.Register<EntityFramework.BulkInsert.Providers.DevartProvider>("Devart.Data.Oracle.OracleConnection");
}
catch (AggregateException ae)
{
if(ae.InnerException is EntityFramework.BulkInsert.Exceptions.BulkInsertProviderNotFoundException)
EntityFramework.BulkInsert.ProviderFactory.Register<EntityFramework.BulkInsert.Providers.DevartProvider>("Devart.Data.Oracle.OracleConnection");
else
throw;
}
}
}
}
@Thorium
Copy link
Author

Thorium commented Jan 16, 2015

I hope to get this some how as part of EntityFramework.BulkInsert core:
https://efbulkinsert.codeplex.com/

@Thorium
Copy link
Author

Thorium commented Mar 9, 2015

Another option would be generating the SQL-clause manually using Oracle array-parameters (":COL").

@Thorium
Copy link
Author

Thorium commented May 6, 2015

Ok, the new version of Devart OracleLoader doesn't work with multi-thread environment so rather use this kind of solution:
Thorium/EntityFramework.BulkInsert@d59f9ae

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment