【问题标题】:What's wrong with this DataTable while SqlBulkCopy-ing from an Entity?从实体执行 SqlBulkCopy 时,此 DataTable 有什么问题?
【发布时间】:2009-10-27 12:06:19
【问题描述】:

我知道下面的方法不适用于任何实体,不应强制使用它。

我找到了一个 System.Data.Linq.Table 扩展方法,它使用 SqlBulkCopy 插入数据。我正在尝试使其适应实体框架,但它引发了一个奇怪的异常,而原来的适用于 Linq-To-Sql 数据类。到目前为止,我找不到该缺陷,它发生在任何 SQL 表中,在 1-1 映射中。你能帮帮我吗?

public static class ObjectQueryExtensions
{
    public static string GetName<TEntity>(
        this ObjectQuery<TEntity> objectQuery)
        where TEntity : class
    {
        var tableNameGroup = new Regex(@"FROM\s([^\s]*)\s"
            , RegexOptions.IgnoreCase);
        var sql = objectQuery.ToTraceString();
        var tableNameGroupMatch = tableNameGroup.Match(sql);
        return tableNameGroupMatch.Groups[1].Value;
    }

    public static void BulkInsert<TEntity>(
          this ObjectQuery<TEntity> objectQuery
        , IEnumerable<TEntity> items)
        where TEntity : class
    {
        using (var dt = new DataTable())
        {
            var properties = typeof(TEntity)
                .GetProperties()
                .Where(property => property.Name  != "EntityKey")
                .Where(property => property.Name  != "EntityState")
                ;
            foreach (var property in properties)
            {
                dt.Columns.Add(property.Name
                   , Nullable.GetUnderlyingType(property.PropertyType)
                   ?? property.PropertyType);
            }

            foreach (var t in items)
            {
                DataRow row = dt.NewRow();
                foreach (var info in properties)
                {
                    row[info.Name] = info.GetValue(t, null) ?? DBNull.Value;
                }
                dt.Rows.Add(row);
            }

            var entityConnection = (EntityConnection)objectQuery
                .Context.Connection;
            using (var sqlBulkCopy = new SqlBulkCopy(
                 entityConnection.StoreConnection.ConnectionString))
            {
                sqlBulkCopy.DestinationTableName = objectQuery.GetName();
                sqlBulkCopy.WriteToServer(dt);
            }
        }
    }
}

例外

测试方法 LinqExtensionsTest.ObjectQueryExtensionsTest.BulkInsertTest 抛出异常:System.InvalidOperationException:来自数据源的 Int64 类型的给定值无法转换为指定目标列的日期时间类型。 ---> System.InvalidCastException:无法将参数值从 Int64 转换为 DateTime。 ---> System.InvalidCastException:从“Int64”到“DateTime”的无效转换..

堆栈跟踪

System.Int64.System.IConvertible.ToDateTime(IFormatProvider 提供程序) System.Convert.ChangeType(对象值,类型转换类型,IFormatProvider 提供程序) System.Data.SqlClient.SqlParameter.CoerceValue(对象值,元类型destinationType) System.Data.SqlClient.SqlParameter.CoerceValue(对象值,元类型destinationType) System.Data.SqlClient.SqlBulkCopy.ConvertValue(对象值,_SqlMetaData 元数据) System.Data.SqlClient.SqlBulkCopy.ConvertValue(对象值,_SqlMetaData 元数据) System.Data.SqlClient.SqlBulkCopy.WriteToServerInternal() System.Data.SqlClient.SqlBulkCopy.WriteRowSourceToServer(Int32 columnCount) System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable 表,DataRowState 行状态) System.Data.SqlClient.SqlBulkCopy.WriteToServer(DataTable 表) LinqExtensions\LinqExtensions\ObjectQueryExtensions.cs 中的 LinqExtensions.ObjectQueryExtensions.BulkInsert[TEntity](ObjectQuery1 objectQuery, IEnumerable1 项):第 60 行 LinqExtensions\LinqExtensionsTest\ObjectQueryExtensionsTest.cs 中的 LinqExtensionsTest.ObjectQueryExtensionsTest.BulkInsertTest():第 88 行

【问题讨论】:

    标签: c# .net linq entity-framework datatable


    【解决方案1】:

    我知道您从实体创建了 DataTable,但我的建议是检查 DataTable 中列的顺序是否与表中的列相同(也许您更改了数据库并且没有更新您的模型)。如果不一样,您可能有不匹配的数据类型并遇到无效转换错误。它发生在我身上;)

    【讨论】:

    • 是的,如果您对数据库进行任何未反映在 edmx 文件上的修改,它将引导您解决该问题。如果 edmx 上的列顺序与数据库表上的顺序不匹配,则会导致您出现这种异常。
    • 实体和数据库中不同列顺序的解决方案是to use column mappings
    【解决方案2】:

    你得到的异常说明了一切:在你的实体对象中,你有一个Int64 类型的属性,它在数据库中定义为DateTime,并且没有办法从一个隐式转换到另一个。您真的打算将该数据库列表示为整数吗?可能只是实体类的定义有误。

    【讨论】:

    • 你的答案是最明显的,但我很难相信,因为我使用Visual Studio实体设计器创建实体类,它不会有这样的错误。
    • 我还重新检查了 DataTable 和 Sql Profiler 中的每个字段,您的怀疑没有得到证实。
    • 这显然是一个类型错误,它不是来自设计师。但这仍然是一个类型错误。它不在您在此处显示的代码中,而是在您的项目中。所以你必须查找堆栈并找到错误。
    • 我将不得不进入 .NET 代码以了解如何规避此问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-02
    相关资源
    最近更新 更多