如何在非关系表上使用实体框架执行批量上载

时间:2018-02-21 12:16:04

标签: c# sql-server entity-framework ef-fluent-api

我有3张桌子

CREATE TABLE [dbo].[TableA](
[TableAID] [bigint] IDENTITY(1,1) NOT NULL,
[PipelineId] [char](10) NULL,
[PipelinePointId] [char](20) NULL,
[Formula] [varchar](500) NULL,
[PipelinePriority] [smallint] NULL

CREATE TABLE [dbo].[TableB](
[TableBID] [smallint] IDENTITY(1,1) NOT NULL,
[UtilityId] [varchar](10) NULL,
[PoolId] [varchar](20) NULL,
[CustomerId] [int] NULL,
[AssetId] [smallint] NULL,
[StartDate] [datetime] NULL,
[EndDate] [datetime] NULL


CREATE TABLE [dbo].[JuntionTable](
[JunctionTableID] [bigint] IDENTITY(1,1) NOT NULL,
[TableAID] [bigint] NOT NULL,
[ParentID] [smallint] NOT NULL, --(ParentID is TableBID)
[AssetType] [nchar](10) NULL,

我们如何通过实体框架工作在此表中插入数据? 我们正在使用Fluent API

插入序列是

  1. 插入TalbeA
  2. 插入表B
  3. 使用JuntionTable.TableAID作为TalbeAID插入到JunctionTable中 JunctionTable.ParentID为TableBID
  4. 我们不能在JunctionTable中使用外键关系,因为联结表将保存来自不同表的数据。

2 个答案:

答案 0 :(得分:0)

您可以使用SQLBulkCopy执行此操作,类似于以下内容:

using (var bulkCopy = new SqlBulkCopy(_DbContext.Database.Connection.ConnectionString, SqlBulkCopyOptions.TableLock))
        {
            bulkCopy.BulkCopyTimeout = 1200; // 20 minutes
            //bulkCopy.BatchSize = listTableColumns.Count();
            bulkCopy.BatchSize = 10000;
            bulkCopy.DestinationTableName = "TableA";

            var table = new DataTable();
            var props = TypeDescriptor.GetProperties(typeof(TableA))                                     
                //Dirty hack to make sure we only have system data types                                      
                //i.e. filter out the relationships/collections
                .Cast<PropertyDescriptor>()
                .Where(propertyInfo => propertyInfo.PropertyType.Namespace.Equals("System"))
                .ToArray();
            foreach (var propertyInfo in props) 
            { 
                bulkCopy.ColumnMappings.Add(propertyInfo.Name, propertyInfo.Name); 
                table.Columns.Add(propertyInfo.Name, Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType); 
            }
            // Add Database ID
            bulkCopy.ColumnMappings.Add("TableAID", "TableAID");
            table.Columns.Add("TableAID", typeof(int));

            var values = new object[props.Length + 1];
            foreach (var item in MyRowsToInsert) 
            { 
                for (var i = 0; i < values.Length - 1; i++) 
                { 
                    values[i] = props[i].GetValue(item);
                }
                table.Rows.Add(values);
            }

            bulkCopy.WriteToServer(table);
        }

答案 1 :(得分:0)

请尝试下面的内容,在代码中通过在每个实体中包含集合属性来定义多对多关系

public class Book
{
    public int BookId { get; set; }
    public string Title { get; set; }
    public Author Author { get; set; }
    public ICollection<BookCategory> BookCategories { get; set; }
} 

public class Category
{
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
    public ICollection<BookCategory> BookCategories { get; set; }
}

public class BookCategory
{
    public int BookId { get; set; }
    public Book Book { get; set; }
    public int CategoryId { get; set; }
    public Category Category { get; set; }
}

- 您必须通过Fluent API为EF Core 1.1.0配置关系才能成功映射,如下所示

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<BookCategory>()
        .HasKey(bc => new { bc.BookId, bc.CategoryId });

    modelBuilder.Entity<BookCategory>()
        .HasOne(bc => bc.Book)
        .WithMany(b => b.BookCategories)
        .HasForeignKey(bc => bc.BookId);

    modelBuilder.Entity<BookCategory>()
        .HasOne(bc => bc.Category)
        .WithMany(c => c.BookCategories)
        .HasForeignKey(bc => bc.CategoryId);
}