c# इकाई फ्रेमवर्क में सम्मिलित करने का सबसे तेज़ तरीका




sql entity-framework (20)

All the solutions written here don't help because when you do SaveChanges(), insert statements are sent to database one by one, that's how Entity works.

And if your trip to database and back is 50 ms for instance then time needed for insert is number of records x 50 ms.

You have to use BulkInsert, here is the link: https://efbulkinsert.codeplex.com/

I got insert time reduced from 5-6 minutes to 10-12 seconds by using it.

मैं एंटिटी फ्रेमवर्क में डालने का सबसे तेज़ तरीका ढूंढ रहा हूं।

मैं इस परिदृश्य के कारण यह पूछ रहा हूं कि आपके पास एक सक्रिय लेनदेनस्कोप है और सम्मिलन विशाल है (4000+)। यह संभावित रूप से 10 मिनट से अधिक (लेनदेन का डिफ़ॉल्ट समय समाप्ति) कर सकता है, और इससे अपूर्ण लेनदेन हो जाएगा।


रहस्य एक समान रिक्त स्टेजिंग टेबल में डालना है। आवेषण जल्दी हल्का कर रहे हैं। फिर उस से एक बड़ी डालने को अपनी मुख्य बड़ी तालिका में चलाएं। फिर अगले बैच के लिए तैयार स्टेजिंग टेबल को छोटा करें।

अर्थात।

insert into some_staging_table using Entity Framework.

-- Single insert into main table (this could be a tiny stored proc call)
insert into some_main_already_large_table (columns...)
   select (columns...) from some_staging_table
truncate table some_staging_table

एक संग्रहीत प्रक्रिया का उपयोग करने का प्रयास करें जो उस डेटा का एक्सएमएल प्राप्त करेगा जिसे आप सम्मिलित करना चाहते हैं।


क्या आपने कभी पृष्ठभूमि कार्यकर्ता या कार्य के माध्यम से सम्मिलित करने का प्रयास किया है?

मेरे मामले में, मैं 7760 रजिस्टरों को सम्मिलित कर रहा हूं, जो 182 विभिन्न तालिकाओं में विदेशी कुंजी संबंधों (नेविगेशनप्रॉपर्टीज द्वारा) में वितरित किए गए हैं।

कार्य के बिना, इसमें 2 मिनट लग गए। एक कार्य के भीतर (कार्य। Task.Factory.StartNew(...) ), इसमें 15 सेकंड लग गए।

संदर्भ में सभी इकाइयों को जोड़ने के बाद मैं केवल SaveChanges() कर रहा SaveChanges() । (डेटा अखंडता सुनिश्चित करने के लिए)


सबसे तेज़ तरीका थोक सम्मिलित विस्तार का उपयोग करेगा, जिसे मैंने विकसित किया था।

यह अधिकतम प्रदर्शन प्राप्त करने के लिए एसक्यूएलकल्क कॉपी और कस्टम डेटाएडर का उपयोग करता है। नतीजतन यह नियमित डालने या AddRange का उपयोग करने से 20 गुना तेजी से है

उपयोग बेहद सरल है

context.BulkInsert(hugeAmountOfEntities);

आपके प्रश्न पर टिप्पणियों में आपकी टिप्पणी के लिए:

"... सेविंग चेंज ( प्रत्येक रिकॉर्ड के लिए ) ..."

यह सबसे बुरी चीज है जो आप कर सकते हैं! प्रत्येक रिकॉर्ड के लिए SaveChanges() को कॉल करना थोक प्रविष्टियों को बहुत धीमा कर देता है। मैं कुछ सरल परीक्षण करता हूं जो प्रदर्शन में काफी सुधार करेंगे:

  • सभी रिकॉर्ड के बाद एक बार SaveChanges() कॉल करें।
  • उदाहरण के लिए 100 रिकॉर्ड के बाद SaveChanges() को कॉल करें।
  • उदाहरण के लिए SaveChanges() को कॉल करें उदाहरण के लिए 100 रिकॉर्ड और संदर्भ का निपटान करें और एक नया बनाएं।
  • परिवर्तन पहचान अक्षम करें

थोक आवेषण के लिए मैं इस तरह के पैटर्न के साथ काम कर रहा हूं और प्रयोग कर रहा हूं:

using (TransactionScope scope = new TransactionScope())
{
    MyDbContext context = null;
    try
    {
        context = new MyDbContext();
        context.Configuration.AutoDetectChangesEnabled = false;

        int count = 0;            
        foreach (var entityToInsert in someCollectionOfEntitiesToInsert)
        {
            ++count;
            context = AddToContext(context, entityToInsert, count, 100, true);
        }

        context.SaveChanges();
    }
    finally
    {
        if (context != null)
            context.Dispose();
    }

    scope.Complete();
}

private MyDbContext AddToContext(MyDbContext context,
    Entity entity, int count, int commitCount, bool recreateContext)
{
    context.Set<Entity>().Add(entity);

    if (count % commitCount == 0)
    {
        context.SaveChanges();
        if (recreateContext)
        {
            context.Dispose();
            context = new MyDbContext();
            context.Configuration.AutoDetectChangesEnabled = false;
        }
    }

    return context;
}

मेरे पास एक परीक्षण कार्यक्रम है जो डीबी में 560,000 इकाइयों (9 स्केलर गुण, कोई नेविगेशन गुण) सम्मिलित करता है। इस कोड के साथ यह 3 मिनट से भी कम समय में काम करता है।

प्रदर्शन के लिए "कई" रिकॉर्ड ("कई" लगभग 100 या 1000) के बाद SaveChanges() को कॉल करना महत्वपूर्ण है। यह SaveChanges के बाद संदर्भ को निपटाने और एक नया निर्माण करने के प्रदर्शन को भी बेहतर बनाता है। यह सभी entites से संदर्भ को साफ़ करता है, SaveChanges ऐसा नहीं करता है, संस्थाएं अभी भी राज्य Unchanged संदर्भ में संलग्न हैं। यह संदर्भ में संलग्न इकाइयों का बढ़ता आकार है जो कदम से सम्मिलन चरण को धीमा कर देता है। तो, कुछ समय बाद इसे साफ़ करना सहायक होता है।

यहां मेरी 560,000 इकाइयों के लिए कुछ माप दिए गए हैं:

  • commitकाउंट = 1, recreateContext = false: कई घंटे (यह आपकी वर्तमान प्रक्रिया है)
  • commitकाउंट = 100, recreateContext = false: 20 मिनट से अधिक
  • commitकाउंट = 1000, recreateContext = false: 242 सेकंड
  • commitकाउंट = 10000, recreateContext = false: 202 सेकंड
  • commitकाउंट = 100000, recreateContext = false: 199 सेकंड
  • commitकाउंट = 1000000, recreateContext = false: स्मृति अपवाद से बाहर
  • commitकाउंट = 1, recreateContext = true: 10 मिनट से अधिक
  • commitकाउंट = 10, recreateContext = true: 241 सेकंड
  • commitकाउंट = 100, recreateContext = true: 164 सेकंड
  • commitकाउंट = 1000, recreateContext = true: 1 9 1 सेकंड

उपरोक्त पहले परीक्षण में व्यवहार यह है कि प्रदर्शन बहुत गैर-रैखिक है और समय के साथ बेहद कम हो जाता है। ("कई घंटे" एक अनुमान है, मैंने कभी भी इस परीक्षा को समाप्त नहीं किया, मैंने 20 मिनट के बाद 50,000 इकाइयों को रोक दिया।) यह गैर-रैखिक व्यवहार अन्य सभी परीक्षणों में इतना महत्वपूर्ण नहीं है।


SqlBulkCopy उपयोग करें:

void BulkInsert(GpsReceiverTrack[] gpsReceiverTracks)
{
    if (gpsReceiverTracks == null)
    {
        throw new ArgumentNullException(nameof(gpsReceiverTracks));
    }

    DataTable dataTable = new DataTable("GpsReceiverTracks");
    dataTable.Columns.Add("ID", typeof(int));
    dataTable.Columns.Add("DownloadedTrackID", typeof(int));
    dataTable.Columns.Add("Time", typeof(TimeSpan));
    dataTable.Columns.Add("Latitude", typeof(double));
    dataTable.Columns.Add("Longitude", typeof(double));
    dataTable.Columns.Add("Altitude", typeof(double));

    for (int i = 0; i < gpsReceiverTracks.Length; i++)
    {
        dataTable.Rows.Add
        (
            new object[]
            {
                    gpsReceiverTracks[i].ID,
                    gpsReceiverTracks[i].DownloadedTrackID,
                    gpsReceiverTracks[i].Time,
                    gpsReceiverTracks[i].Latitude,
                    gpsReceiverTracks[i].Longitude,
                    gpsReceiverTracks[i].Altitude
            }
        );
    }

    string connectionString = (new TeamTrackerEntities()).Database.Connection.ConnectionString;
    using (var connection = new SqlConnection(connectionString))
    {
        connection.Open();
        using (var transaction = connection.BeginTransaction())
        {
            using (var sqlBulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, transaction))
            {
                sqlBulkCopy.DestinationTableName = dataTable.TableName;
                foreach (DataColumn column in dataTable.Columns)
                {
                    sqlBulkCopy.ColumnMappings.Add(column.ColumnName, column.ColumnName);
                }

                sqlBulkCopy.WriteToServer(dataTable);
            }
            transaction.Commit();
        }
    }

    return;
}

मैं एंटिटी फ्रेमवर्क में डालने का सबसे तेज़ तरीका ढूंढ रहा हूं

बल्क सम्मिलन का समर्थन करने वाली कुछ तीसरी पार्टी लाइब्रेरी उपलब्ध है:

  • Z.EntityFramework.Extensions ( अनुशंसित )
  • EFUtilities
  • EntityFramework.BulkInsert

देखें: इकाई फ्रेमवर्क थोक सम्मिलित लाइब्रेरी

थोक डालने लाइब्रेरी चुनते समय सावधान रहें। केवल इकाई फ्रेमवर्क एक्सटेंशन सभी प्रकार के संगठनों और विरासत का समर्थन करते हैं और यह अभी भी समर्थित है।

अस्वीकरण : मैं इकाई फ्रेमवर्क एक्सटेंशन का मालिक हूं

यह पुस्तकालय आपको अपने परिदृश्यों के लिए आवश्यक सभी थोक संचालन करने की अनुमति देता है:

  • थोक SaveChanges
  • थोक सम्मिलित करें
  • थोक हटाएं
  • थोक अद्यतन
  • थोक मर्ज

उदाहरण

// Easy to use
context.BulkSaveChanges();

// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);

// Perform Bulk Operations
context.BulkDelete(customers);
context.BulkInsert(customers);
context.BulkUpdate(customers);

// Customize Primary Key
context.BulkMerge(customers, operation => {
   operation.ColumnPrimaryKeyExpression = 
        customer => customer.Code;
});

मैंने ऊपर @ स्लुमा के उदाहरण का एक सामान्य विस्तार किया है;

public static class DataExtensions
{
    public static DbContext AddToContext<T>(this DbContext context, object entity, int count, int commitCount, bool recreateContext, Func<DbContext> contextCreator)
    {
        context.Set(typeof(T)).Add((T)entity);

        if (count % commitCount == 0)
        {
            context.SaveChanges();
            if (recreateContext)
            {
                context.Dispose();
                context = contextCreator.Invoke();
                context.Configuration.AutoDetectChangesEnabled = false;
            }
        }
        return context;
    }
}

उपयोग:

public void AddEntities(List<YourEntity> entities)
{
    using (var transactionScope = new TransactionScope())
    {
        DbContext context = new YourContext();
        int count = 0;
        foreach (var entity in entities)
        {
            ++count;
            context = context.AddToContext<TenancyNote>(entity, count, 100, true,
                () => new YourContext());
        }
        context.SaveChanges();
        transactionScope.Complete();
    }
}

इसके लिए आपको System.Data.SqlClient.SqlBulkCopy का उपयोग करना चाहिए। यहां documentation , और निश्चित रूप से ऑनलाइन बहुत सारे ट्यूटोरियल हैं।

क्षमा करें, मुझे पता है कि आप जो चाहते हैं उसे करने के लिए ईएफ प्राप्त करने के लिए एक सरल उत्तर की तलाश में थे, लेकिन थोक संचालन वास्तव में नहीं हैं कि ओआरएम का क्या अर्थ है।


But, for more than (+4000) inserts i recommend to use stored procedure. attached the time elapsed. I did inserted it 11.788 rows in 20"

thats it code

 public void InsertDataBase(MyEntity entity)
    {
        repository.Database.ExecuteSqlCommand("sp_mystored " +
                "@param1, @param2"
                 new SqlParameter("@param1", entity.property1),
                 new SqlParameter("@param2", entity.property2));
    }


मुझे पता है कि यह एक बहुत पुराना सवाल है, लेकिन यहां एक व्यक्ति ने कहा कि ईएफ के साथ थोक सम्मिलन का उपयोग करने के लिए एक विस्तार विधि विकसित की गई, और जब मैंने चेक किया, तो मुझे पता चला कि लाइब्रेरी आज $ 59 9 (एक डेवलपर के लिए) खर्च करती है। शायद यह पूरी लाइब्रेरी के लिए समझ में आता है, हालांकि केवल थोक डालने के लिए यह बहुत अधिक है।

यहां मैंने बनाया एक बहुत ही सरल विस्तार विधि है। मैं इसे पहले डेटाबेस के साथ जोड़ी पर उपयोग करता हूं (पहले कोड के साथ परीक्षण नहीं किया जाता है, लेकिन मुझे लगता है कि यह वही काम करता है)। अपने संदर्भ के नाम से अपनी YourEntities बदलें:

public partial class YourEntities : DbContext
{
    public async Task BulkInsertAllAsync<T>(IEnumerable<T> entities)
    {
        using (var conn = new SqlConnection(Database.Connection.ConnectionString))
        {
            conn.Open();

            Type t = typeof(T);

            var bulkCopy = new SqlBulkCopy(conn)
            {
                DestinationTableName = GetTableName(t)
            };

            var table = new DataTable();

            var properties = t.GetProperties().Where(p => p.PropertyType.IsValueType || p.PropertyType == typeof(string));

            foreach (var property in properties)
            {
                Type propertyType = property.PropertyType;
                if (propertyType.IsGenericType &&
                    propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    propertyType = Nullable.GetUnderlyingType(propertyType);
                }

                table.Columns.Add(new DataColumn(property.Name, propertyType));
            }

            foreach (var entity in entities)
            {
                table.Rows.Add(
                    properties.Select(property => property.GetValue(entity, null) ?? DBNull.Value).ToArray());
            }

            bulkCopy.BulkCopyTimeout = 0;
            await bulkCopy.WriteToServerAsync(table);
        }
    }

    public void BulkInsertAll<T>(IEnumerable<T> entities)
    {
        using (var conn = new SqlConnection(Database.Connection.ConnectionString))
        {
            conn.Open();

            Type t = typeof(T);

            var bulkCopy = new SqlBulkCopy(conn)
            {
                DestinationTableName = GetTableName(t)
            };

            var table = new DataTable();

            var properties = t.GetProperties().Where(p => p.PropertyType.IsValueType || p.PropertyType == typeof(string));

            foreach (var property in properties)
            {
                Type propertyType = property.PropertyType;
                if (propertyType.IsGenericType &&
                    propertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    propertyType = Nullable.GetUnderlyingType(propertyType);
                }

                table.Columns.Add(new DataColumn(property.Name, propertyType));
            }

            foreach (var entity in entities)
            {
                table.Rows.Add(
                    properties.Select(property => property.GetValue(entity, null) ?? DBNull.Value).ToArray());
            }

            bulkCopy.BulkCopyTimeout = 0;
            bulkCopy.WriteToServer(table);
        }
    }

    public string GetTableName(Type type)
    {
        var metadata = ((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace;
        var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));

        var entityType = metadata
                .GetItems<EntityType>(DataSpace.OSpace)
                .Single(e => objectItemCollection.GetClrType(e) == type);

        var entitySet = metadata
            .GetItems<EntityContainer>(DataSpace.CSpace)
            .Single()
            .EntitySets
            .Single(s => s.ElementType.Name == entityType.Name);

        var mapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
                .Single()
                .EntitySetMappings
                .Single(s => s.EntitySet == entitySet);

        var table = mapping
            .EntityTypeMappings.Single()
            .Fragments.Single()
            .StoreEntitySet;

        return (string)table.MetadataProperties["Table"].Value ?? table.Name;
    }
}

आप इसका उपयोग किसी भी संग्रह के खिलाफ कर सकते हैं जो आईनेमेरेबल से प्राप्त होता है, जैसे कि:

await context.BulkInsertAllAsync(items);

मैं इस लेख की सिफारिश करता हूं कि ईएफ का उपयोग करके थोक आवेषण कैसे करें।

इकाई फ्रेमवर्क और धीमी थोक INSERTs

वह इन क्षेत्रों की खोज करता है और परफॉर्मेंस की तुलना करता है:

  1. डिफ़ॉल्ट ईएफ (30,000 रिकॉर्ड जोड़ने को पूरा करने के लिए 57 मिनट)
  2. ADO.NET कोड के साथ प्रतिस्थापित (उन 30,000 के लिए 25 सेकंड )
  3. संदर्भ ब्लोट- कार्य के प्रत्येक इकाई के लिए एक नए संदर्भ का उपयोग करके सक्रिय संदर्भ ग्राफ को छोटा रखें (उसी 30,000 प्रविष्टियों में 33 सेकंड लगते हैं)
  4. बड़ी सूची - AutoDetectChangesEnabled बंद करें (समय को लगभग 20 सेकंड तक लाता है)
  5. बैचिंग (16 सेकंड तक)
  6. DbTable.AddRange () - (प्रदर्शन 12 रेंज में है)

निपटान () संदर्भ समस्याएं पैदा करते हैं यदि आप जो संस्थाएं जोड़ते हैं () संदर्भ में अन्य प्रीलोडेड इकाइयों (जैसे नेविगेशन गुण) पर भरोसा करते हैं

मैं एक ही प्रदर्शन को प्राप्त करने के लिए अपना संदर्भ छोटा रखने के लिए समान अवधारणा का उपयोग करता हूं

लेकिन संदर्भ () को संदर्भित करने और पुनर्निर्मित करने के बजाय, मैं बस उन इकाइयों को अलग करता हूं जो पहले से ही SaveChanges ()

public void AddAndSave<TEntity>(List<TEntity> entities) where TEntity : class {

const int CommitCount = 1000; //set your own best performance number here
int currentCount = 0;

while (currentCount < entities.Count())
{
    //make sure it don't commit more than the entities you have
    int commitCount = CommitCount;
    if ((entities.Count - currentCount) < commitCount)
        commitCount = entities.Count - currentCount;

    //e.g. Add entities [ i = 0 to 999, 1000 to 1999, ... , n to n+999... ] to conext
    for (int i = currentCount; i < (currentCount + commitCount); i++)        
        _context.Entry(entities[i]).State = System.Data.EntityState.Added;
        //same as calling _context.Set<TEntity>().Add(entities[i]);       

    //commit entities[n to n+999] to database
    _context.SaveChanges();

    //detach all entities in the context that committed to database
    //so it won't overload the context
    for (int i = currentCount; i < (currentCount + commitCount); i++)
        _context.Entry(entities[i]).State = System.Data.EntityState.Detached;

    currentCount += commitCount;
} }

इसे पकड़ने की कोशिश करें और TrasactionScope () यदि आपको आवश्यकता हो, तो कोड को साफ रखने के लिए उन्हें यहां नहीं दिखाया जा रहा है


मेरे ज्ञान के अनुसार विशाल आवेषण के प्रदर्शन को बढ़ाने के लिए no BulkInsert में no BulkInsert प्रविष्टि नहीं है।

इस परिदृश्य में आप अपनी समस्या का समाधान करने के लिए ADO.net में documentation साथ जा सकते हैं


[NEW SOLUTION FOR POSTGRESQL] Hey, I know it's quite an old post, but I have recently run into similar problem, but we were using Postgresql. I wanted to use effective bulkinsert, what turned out to be pretty difficult. I haven't found any proper free library to do so on this DB. I have only found this helper: https://bytefish.de/blog/postgresql_bulk_insert/ which is also on Nuget. I have written a small mapper, which auto mapped properties the way Entity Framework:

public static PostgreSQLCopyHelper<T> CreateHelper<T>(string schemaName, string tableName)
        {
            var helper = new PostgreSQLCopyHelper<T>("dbo", "\"" + tableName + "\"");
            var properties = typeof(T).GetProperties();
            foreach(var prop in properties)
            {
                var type = prop.PropertyType;
                if (Attribute.IsDefined(prop, typeof(KeyAttribute)) || Attribute.IsDefined(prop, typeof(ForeignKeyAttribute)))
                    continue;
                switch (type)
                {
                    case Type intType when intType == typeof(int) || intType == typeof(int?):
                        {
                            helper = helper.MapInteger("\"" + prop.Name + "\"",  x => (int?)typeof(T).GetProperty(prop.Name).GetValue(x, null));
                            break;
                        }
                    case Type stringType when stringType == typeof(string):
                        {
                            helper = helper.MapText("\"" + prop.Name + "\"", x => (string)typeof(T).GetProperty(prop.Name).GetValue(x, null));
                            break;
                        }
                    case Type dateType when dateType == typeof(DateTime) || dateType == typeof(DateTime?):
                        {
                            helper = helper.MapTimeStamp("\"" + prop.Name + "\"", x => (DateTime?)typeof(T).GetProperty(prop.Name).GetValue(x, null));
                            break;
                        }
                    case Type decimalType when decimalType == typeof(decimal) || decimalType == typeof(decimal?):
                        {
                            helper = helper.MapMoney("\"" + prop.Name + "\"", x => (decimal?)typeof(T).GetProperty(prop.Name).GetValue(x, null));
                            break;
                        }
                    case Type doubleType when doubleType == typeof(double) || doubleType == typeof(double?):
                        {
                            helper = helper.MapDouble("\"" + prop.Name + "\"", x => (double?)typeof(T).GetProperty(prop.Name).GetValue(x, null));
                            break;
                        }
                    case Type floatType when floatType == typeof(float) || floatType == typeof(float?):
                        {
                            helper = helper.MapReal("\"" + prop.Name + "\"", x => (float?)typeof(T).GetProperty(prop.Name).GetValue(x, null));
                            break;
                        }
                    case Type guidType when guidType == typeof(Guid):
                        {
                            helper = helper.MapUUID("\"" + prop.Name + "\"", x => (Guid)typeof(T).GetProperty(prop.Name).GetValue(x, null));
                            break;
                        }
                }
            }
            return helper;
        }

I use it the following way (I had entity named Undertaking):

var undertakingHelper = BulkMapper.CreateHelper<Model.Undertaking>("dbo", nameof(Model.Undertaking));
undertakingHelper.SaveAll(transaction.UnderlyingTransaction.Connection as Npgsql.NpgsqlConnection, undertakingsToAdd));

I showed an example with transaction, but it can also be done with normal connection retrieved from context. undertakingsToAdd is enumerable of normal entity records, which I want to bulkInsert into DB.

This solution, to which I've got after few hours of research and trying, is as you could expect much faster and finally easy to use and free! I really advice you to use this solution, not only for the reasons mentioned above, but also because it's the only one with which I had no problems with Postgresql itself, many other solutions work flawlessly for example with SqlServer.


मैं एडम रैकीस से सहमत हूं। SqlBulkCopy एक डेटा स्रोत से दूसरे डेटा में थोक रिकॉर्ड स्थानांतरित करने का सबसे तेज़ तरीका है। मैंने 20K रिकॉर्ड कॉपी करने के लिए इसका इस्तेमाल किया और इसमें 3 सेकंड से भी कम समय लगा। नीचे दिए गए उदाहरण पर एक नज़र डालें।

public static void InsertIntoMembers(DataTable dataTable)
{           
    using (var connection = new SqlConnection(@"data source=;persist security info=True;user id=;password=;initial catalog=;MultipleActiveResultSets=True;App=EntityFramework"))
    {
        SqlTransaction transaction = null;
        connection.Open();
        try
        {
            transaction = connection.BeginTransaction();
            using (var sqlBulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, transaction))
            {
                sqlBulkCopy.DestinationTableName = "Members";
                sqlBulkCopy.ColumnMappings.Add("Firstname", "Firstname");
                sqlBulkCopy.ColumnMappings.Add("Lastname", "Lastname");
                sqlBulkCopy.ColumnMappings.Add("DOB", "DOB");
                sqlBulkCopy.ColumnMappings.Add("Gender", "Gender");
                sqlBulkCopy.ColumnMappings.Add("Email", "Email");

                sqlBulkCopy.ColumnMappings.Add("Address1", "Address1");
                sqlBulkCopy.ColumnMappings.Add("Address2", "Address2");
                sqlBulkCopy.ColumnMappings.Add("Address3", "Address3");
                sqlBulkCopy.ColumnMappings.Add("Address4", "Address4");
                sqlBulkCopy.ColumnMappings.Add("Postcode", "Postcode");

                sqlBulkCopy.ColumnMappings.Add("MobileNumber", "MobileNumber");
                sqlBulkCopy.ColumnMappings.Add("TelephoneNumber", "TelephoneNumber");

                sqlBulkCopy.ColumnMappings.Add("Deleted", "Deleted");

                sqlBulkCopy.WriteToServer(dataTable);
            }
            transaction.Commit();
        }
        catch (Exception)
        {
            transaction.Rollback();
        }

    }
}

Use stored procedure that takes input data in form of xml to insert data.

From your c# code pass insert data as xml.

eg in c#, syntax would be like this:

object id_application = db.ExecuteScalar("procSaveApplication", xml)

मैंने स्लामा के जवाब की जांच की है (जो कि कमाल है, विचार आदमी के लिए धन्यवाद), और मैंने बैच आकार को कम कर दिया है जब तक कि मैंने इष्टतम गति नहीं मारा। स्लैमा के परिणामों को देखते हुए:

  • commitकाउंट = 1, recreateContext = true: 10 मिनट से अधिक
  • commitकाउंट = 10, recreateContext = true: 241 सेकंड
  • commitकाउंट = 100, recreateContext = true: 164 सेकंड
  • commitकाउंट = 1000, recreateContext = true: 1 9 1 सेकंड

यह दिखाई देता है कि 1 से 10 तक और 10 से 100 तक की गति बढ़ने पर गति बढ़ जाती है, लेकिन 100 से 1000 तक की गति गति फिर से गिर रही है।

इसलिए मैंने क्या किया है जब आप बैच आकार को 10 और 100 के बीच कहीं भी महत्व देते हैं, और यहां मेरे परिणाम हैं (मैं अलग-अलग पंक्ति सामग्री का उपयोग कर रहा हूं, इसलिए मेरे समय अलग-अलग मान हैं):

Quantity    | Batch size    | Interval
1000    1   3
10000   1   34
100000  1   368

1000    5   1
10000   5   12
100000  5   133

1000    10  1
10000   10  11
100000  10  101

1000    20  1
10000   20  9
100000  20  92

1000    27  0
10000   27  9
100000  27  92

1000    30  0
10000   30  9
100000  30  92

1000    35  1
10000   35  9
100000  35  94

1000    50  1
10000   50  10
100000  50  106

1000    100 1
10000   100 14
100000  100 141

मेरे परिणामों के आधार पर, वास्तविक इष्टतम बैच आकार के लिए 30 के मूल्य के आसपास है। यह 10 और 100 दोनों से कम है। समस्या यह है कि, मुझे नहीं पता कि 30 इष्टतम क्यों है, और न ही मुझे इसके लिए कोई तार्किक स्पष्टीकरण मिल सकता है।





entity-framework