-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} | |
} | |
} | |
} |
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
Another option would be generating the SQL-clause manually using Oracle array-parameters (":COL").