【问题标题】:Using DataTable in .NET Core在 .NET Core 中使用数据表
【发布时间】:2017-02-07 20:03:02
【问题描述】:

我在 SQL Server 中有一个接受用户定义的表类型的存储过程。我正在关注这篇文章 Bulk insert from C# list into SQL Server into multiple tables with foreign key constaints 中关于如何将 DataTable 发送到 SQL 中的存储过程的答案。

但是当我创建 DataTable table = new DataTable(); 时,我收到一个错误 DataTable does not contain a constructor that takes 0 arguments

我发现这个https://github.com/VahidN/EPPlus.Core/issues/4 基本上说DataTable 在.NET Core 中不再支持。那么现在怎么办?如何创建 DataTable(或它的替代品)?如何将用户定义的表类型发送到 .NET Core 上的 SQL Server?

【问题讨论】:

  • 核心现在支持数据表!!!来自帖子:“您必须使用 VS2017 Preview 15.3,以 .net core 2.0 为目标,并为 System.Data.Common 和 System.Data.SqlClient 添加 NuGet 包。代码如下。”快乐编码。 stackoverflow.com/a/43970881/1197405

标签: c# datatable asp.net-core .net-core asp.net-core-1.0


【解决方案1】:

.NET CORE 2.0 现在支持 DataTable。在.Net Core how to implement SQLAdapter ./ DataTable function 上查看我的答案。下面的示例代码适用于 2.0。

public static DataTable ExecuteDataTableSqlDA(SqlConnection conn, CommandType cmdType, string cmdText, SqlParameter[] cmdParms)
{
   System.Data.DataTable dt = new DataTable();
   System.Data.SqlClient.SqlDataAdapter da = new SqlDataAdapter(cmdText, conn);
   da.Fill(dt);
   return dt;
}

【讨论】:

  • 我在 .net core 3.0 上,但在 System.Data.SqlClient 中看不到 SqlDataAdapter??
  • 我必须安装nuget包System.Data.Common
  • 谢谢凯尔!正在尝试其他选择。
【解决方案2】:

您可以使用DbDataReader 作为 SQL 参数的值。因此,我们的想法是将IEnumerable<T> 转换为DbDataReader

public class ObjectDataReader<T> : DbDataReader
{
    private bool _iteratorOwned;
    private IEnumerator<T> _iterator;
    private IDictionary<string, int> _propertyNameToOrdinal = new Dictionary<string, int>();
    private IDictionary<int, string> _ordinalToPropertyName = new Dictionary<int, string>();
    private Func<T, object>[] _getPropertyValueFuncs;

    public ObjectDataReader(IEnumerable<T> enumerable)
    {
        if (enumerable == null) throw new ArgumentNullException(nameof(enumerable));

        _iteratorOwned = true;
        _iterator = enumerable.GetEnumerator();
        _iterator.MoveNext();
        Initialize();
    }

    public ObjectDataReader(IEnumerator<T> iterator)
    {
        if (iterator == null) throw new ArgumentNullException(nameof(iterator));

        _iterator = iterator;    
        Initialize();
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && _iteratorOwned)
        {
            if(_iterator != null)
                _iterator.Dispose();
        }

        base.Dispose(disposing);
    }

    private void Initialize()
    {
        int ordinal = 0;
        var properties = typeof(T).GetProperties();
        _getPropertyValueFuncs = new Func<T, object>[properties.Length];
        foreach (var property in properties)
        {
            string propertyName = property.Name;
            _propertyNameToOrdinal.Add(propertyName, ordinal);
            _ordinalToPropertyName.Add(ordinal, propertyName);

            var parameterExpression = Expression.Parameter(typeof(T), "x");
            var func = (Func<T, object>)Expression.Lambda(Expression.Convert(Expression.Property(parameterExpression, propertyName), typeof(object)), parameterExpression).Compile();
            _getPropertyValueFuncs[ordinal] = func;

            ordinal++;
        }
    }

    public override object this[int ordinal] 
    {
        get
        {
            return GetValue(ordinal);
        }
    }

    public override object this[string name]
    {
        get
        {
            return GetValue(GetOrdinal(name));
        }
    }

    public override int Depth => 1;

    public override int FieldCount => _ordinalToPropertyName.Count;

    public override bool HasRows => true;

    public override bool IsClosed
    {
        get
        {
            return _iterator != null;
        }
    }

    public override int RecordsAffected
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public override bool GetBoolean(int ordinal)
    {
        return (bool)GetValue(ordinal);
    }

    public override byte GetByte(int ordinal)
    {
        return (byte)GetValue(ordinal);
    }

    public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)
    {
        throw new NotImplementedException();
    }

    public override char GetChar(int ordinal)
    {
        return (char)GetValue(ordinal);
    }

    public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length)
    {
        throw new NotImplementedException();
    }

    public override string GetDataTypeName(int ordinal)
    {
        throw new NotImplementedException();
    }

    public override DateTime GetDateTime(int ordinal)
    {
        return (DateTime)GetValue(ordinal);
    }

    public override decimal GetDecimal(int ordinal)
    {
        return (decimal)GetValue(ordinal);
    }

    public override double GetDouble(int ordinal)
    {
        return (double)GetValue(ordinal);
    }

    public override IEnumerator GetEnumerator()
    {
        throw new NotImplementedException();
    }

    public override Type GetFieldType(int ordinal)
    {
        var value = GetValue(ordinal);
        if (value == null)
            return typeof(object);

        return value.GetType();
    }

    public override float GetFloat(int ordinal)
    {
        return (float)GetValue(ordinal);
    }

    public override Guid GetGuid(int ordinal)
    {
        return (Guid)GetValue(ordinal);
    }

    public override short GetInt16(int ordinal)
    {
        return (short)GetValue(ordinal);
    }

    public override int GetInt32(int ordinal)
    {
        return (int)GetValue(ordinal);
    }

    public override long GetInt64(int ordinal)
    {
        return (long)GetValue(ordinal);
    }

    public override string GetName(int ordinal)
    {
        string name;
        if (_ordinalToPropertyName.TryGetValue(ordinal, out name))
            return name;

        return null;
    }

    public override int GetOrdinal(string name)
    {
        int ordinal;
        if (_propertyNameToOrdinal.TryGetValue(name, out ordinal))
            return ordinal;

        return -1;
    }

    public override string GetString(int ordinal)
    {
        return (string)GetValue(ordinal);
    }

    public override object GetValue(int ordinal)
    {
        var func = _getPropertyValueFuncs[ordinal];
        return func(_iterator.Current);
    }

    public override int GetValues(object[] values)
    {
        int max = Math.Min(values.Length, FieldCount);
        for (var i = 0; i < max; i++)
        {
            values[i] = IsDBNull(i) ? DBNull.Value : GetValue(i);
        }

        return max;
    }

    public override bool IsDBNull(int ordinal)
    {
        return GetValue(ordinal) == null;
    }

    public override bool NextResult()
    {
        return false;
    }

    public override bool Read()
    {
        return _iterator.MoveNext();
    }
}

那么,你就可以使用这个类了:

static void Main(string[] args)
{
    Console.WriteLine("Hello World!");
    string connectionString = "Server=(local);Database=Sample;Trusted_Connection=True;";

    using (var connection = new SqlConnection(connectionString))
    {
        connection.Open();

        using (var command = connection.CreateCommand())
        {
            command.CommandType = System.Data.CommandType.StoredProcedure;
            command.CommandText = "procMergePageView";

            var p1 = command.CreateParameter();
            command.Parameters.Add(p1);    
            p1.ParameterName = "@Display";
            p1.SqlDbType = System.Data.SqlDbType.Structured;
            var items = PageViewTableType.Generate(100);
            using (DbDataReader dr = new ObjectDataReader<PageViewTableType>(items))
            {
                p1.Value = dr;
                command.ExecuteNonQuery();
            }    
        }
    }
}

class PageViewTableType
{
    // Must match the name of the column of the TVP
    public long PageViewID { get; set; }

    // Generate dummy data
    public static IEnumerable<PageViewTableType> Generate(int count)
    {
        for (int i = 0; i < count; i++)
        {
            yield return new PageViewTableType { PageViewID = i };
        }
    }
}

SQL 脚本:

CREATE TABLE dbo.PageView
(
    PageViewID BIGINT NOT NULL CONSTRAINT pkPageView PRIMARY KEY CLUSTERED,
    PageViewCount BIGINT NOT NULL
);
GO

CREATE TYPE dbo.PageViewTableType AS TABLE
(
    PageViewID BIGINT NOT NULL
);
GO

CREATE PROCEDURE dbo.procMergePageView
    @Display dbo.PageViewTableType READONLY
AS
BEGIN
    MERGE INTO dbo.PageView AS T
    USING @Display AS S
    ON T.PageViewID = S.PageViewID
    WHEN MATCHED THEN UPDATE SET T.PageViewCount = T.PageViewCount + 1
    WHEN NOT MATCHED THEN INSERT VALUES(S.PageViewID, 1);
END

顺便说一句,我写了一个blog post about the ObjectDataReader&lt;T&gt;

【讨论】:

  • 我做了一些修改。如果您有编译错误,请告诉我。
  • 谢谢。我收到一些错误。第一个:Invalid expression term 'throw'
  • 我删除了构造函数中的throw expression,现在应该可以了
  • 仍然是同样的错误和许多其他错误:( - 我无法将它们全部粘贴到这里。你可以尝试在 c# 6 上编译吗?
  • 这次用 C# 6 编译:)
【解决方案3】:

这个问题有两种解决方案。正如@meziantou 在他的回答中所建议的那样,一个人正在使用DbDataReader,并且很高兴提供一个通用方法,将IEnumerable&lt;T&gt; 转换为DbDataReader

我发现的另一个解决方案是使用SqlDataRecord,所以我在这里写下来(使用任何你认为适合你需要的东西):

SQL Server 表:

CREATE TABLE [dbo].[Users](
    [UserId] [int] IDENTITY(1,1) NOT NULL,
    [FirstName] [nvarchar](50) NULL,
    [LastNAme] [nvarchar](50) NULL,
 CONSTRAINT [PK_USers] PRIMARY KEY CLUSTERED 
(
    [UserId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

用户定义的表类型:

CREATE TYPE [dbo].[TblUser] AS TABLE(
    [FirstName] [nvarchar](50) NULL,
    [LastNAme] [nvarchar](50) NULL
)

.NET Core 代码:

var db = new SqlConnection("Server=localhost; Database=Test; User Id=test; Password=123456;");

List<SqlDataRecord> users = new List<SqlDataRecord>();

SqlMetaData mDataFirstName = new SqlMetaData("FirstName", SqlDbType.NVarChar, 50);
SqlMetaData mDataLastName = new SqlMetaData("LastName", SqlDbType.NVarChar, 50);

SqlDataRecord user1 = new SqlDataRecord(new []{ mDataFirstName, mDataLastName });
user1.SetString(0, "Ophir");
user1.SetString(1, "Oren");
users.Add(user1);

SqlParameter param = new SqlParameter("@Users", SqlDbType.Structured)
{
    TypeName = "TblUser",
    Value = users
};

Dictionary<string, object> values = new Dictionary<string, object>();
values.Add("@Users", param);


db.Open();
using (var command = db.CreateCommand())
{
    command.CommandType = System.Data.CommandType.StoredProcedure;
    command.CommandText = "stp_Users_Insert";

    var p1 = command.CreateParameter();
    command.Parameters.Add(p1);
    p1.ParameterName = "@Users";
    p1.SqlDbType = System.Data.SqlDbType.Structured;
    p1.Value = users;
    command.ExecuteNonQuery();
}

【讨论】:

    【解决方案4】:

    @meziantou。我喜欢你的回答,但你的实现中有一个重大错误。第一个问题是在构造函数中调用了 MoveNext,这将导致读取器的任何迭代总是跳过第一个值。一旦我删除了它,我就发现了为什么要这样做。我将 GetFieldType 更改为使用类型信息,而不是从值中读取类型,从而解决了该问题。再次,您的回答非常好。感谢您的发表。这是我修复的 ObjectDataReader 版本。

        public class ObjectDataReader<T> : DbDataReader
        {   
            private bool _iteratorOwned;
            private IEnumerator<T> _iterator;
            private IDictionary<string, int> _propertyNameToOrdinal = new Dictionary<string, int>();
            private IDictionary<int, string> _ordinalToPropertyName = new Dictionary<int, string>();
            private PropertyInfoContainer[] _propertyInfos;
    
            class PropertyInfoContainer
            {
                public Func<T, object> EvaluatePropertyFunction { get; set; }
                public Type PropertyType { get; set; }
                public string PropertyName { get; set; }
                public PropertyInfoContainer(string propertyName
                    , Type propertyType
                    , Func<T, object> evaluatePropertyFunction)
                {
                    this.PropertyName = propertyName;
                    this.PropertyType = propertyType;
                    this.EvaluatePropertyFunction = evaluatePropertyFunction;
                }
            }
    
            public ObjectDataReader(IEnumerable<T> enumerable)
            {
                if (enumerable == null) throw new ArgumentNullException(nameof(enumerable));
    
                _iteratorOwned = true;
                _iterator = enumerable.GetEnumerator();
                //_iterator.MoveNext();
                Initialize();
            }
    
            public ObjectDataReader(IEnumerator<T> iterator)
            {
                if (iterator == null) throw new ArgumentNullException(nameof(iterator));
    
                _iterator = iterator;
                Initialize();
            }
    
            protected override void Dispose(bool disposing)
            {
                if (disposing && _iteratorOwned)
                {
                    if (_iterator != null)
                        _iterator.Dispose();
                }
    
                base.Dispose(disposing);
            }
    
            private void Initialize()
            {
                int ordinal = 0;
                var properties = typeof(T).GetProperties();
                _propertyInfos = new PropertyInfoContainer[properties.Length];
                foreach (var property in properties)
                {
                    string propertyName = property.Name;
                    _propertyNameToOrdinal.Add(propertyName, ordinal);
                    _ordinalToPropertyName.Add(ordinal, propertyName);
    
                    var parameterExpression = Expression.Parameter(typeof(T), "x");
                    var func = (Func<T, object>)Expression.Lambda(Expression.Convert(Expression.Property(parameterExpression, propertyName), typeof(object)), parameterExpression).Compile();
                    _propertyInfos[ordinal] = new PropertyInfoContainer(property.Name
                        , property.PropertyType
                        , func);
    
                    ordinal++;
                }
            }
    
            public override object this[int ordinal]
            {
                get
                {
                    return GetValue(ordinal);
                }
            }
    
            public override object this[string name]
            {
                get
                {
                    return GetValue(GetOrdinal(name));
                }
            }
    
            public override int Depth => 1;
    
            public override int FieldCount => _ordinalToPropertyName.Count;
    
            public override bool HasRows => true;
    
            public override bool IsClosed
            {
                get
                {
                    return _iterator != null;
                }
            }
    
            public override int RecordsAffected
            {
                get
                {
                    throw new NotImplementedException();
                }
            }
    
            public override bool GetBoolean(int ordinal)
            {
                return (bool)GetValue(ordinal);
            }
    
            public override byte GetByte(int ordinal)
            {
                return (byte)GetValue(ordinal);
            }
    
            public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length)
            {
                throw new NotImplementedException();
            }
    
            public override char GetChar(int ordinal)
            {
                return (char)GetValue(ordinal);
            }
    
            public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length)
            {
                throw new NotImplementedException();
            }
    
            public override string GetDataTypeName(int ordinal)
            {
                throw new NotImplementedException();
            }
    
            public override DateTime GetDateTime(int ordinal)
            {
                return (DateTime)GetValue(ordinal);
            }
    
            public override decimal GetDecimal(int ordinal)
            {
                return (decimal)GetValue(ordinal);
            }
    
            public override double GetDouble(int ordinal)
            {
                return (double)GetValue(ordinal);
            }
    
            public override IEnumerator GetEnumerator()
            {
                throw new NotImplementedException();
            }
    
            public override Type GetFieldType(int ordinal)
            {    
                // cannot handle nullable types, so get underlying type
                var propertyType =
                                    Nullable.GetUnderlyingType(_propertyInfos[ordinal].PropertyType) ?? _propertyInfos[ordinal].PropertyType;
    
                return propertyType;
            }
    
            public override float GetFloat(int ordinal)
            {
                return (float)GetValue(ordinal);
            }
    
            public override Guid GetGuid(int ordinal)
            {
                return (Guid)GetValue(ordinal);
            }
    
            public override short GetInt16(int ordinal)
            {
                return (short)GetValue(ordinal);
            }
    
            public override int GetInt32(int ordinal)
            {
                return (int)GetValue(ordinal);
            }
    
            public override long GetInt64(int ordinal)
            {
                return (long)GetValue(ordinal);
            }
    
            public override string GetName(int ordinal)
            {
                string name;
                if (_ordinalToPropertyName.TryGetValue(ordinal, out name))
                    return name;
    
                return null;
            }
    
            public override int GetOrdinal(string name)
            {
                int ordinal;
                if (_propertyNameToOrdinal.TryGetValue(name, out ordinal))
                    return ordinal;
    
                return -1;
            }
    
            public override string GetString(int ordinal)
            {
                return (string)GetValue(ordinal);
            }
    
            public override object GetValue(int ordinal)
            {
                var func = _propertyInfos[ordinal].EvaluatePropertyFunction;
                return func(_iterator.Current);
            }
    
            public override int GetValues(object[] values)
            {
                int max = Math.Min(values.Length, FieldCount);
                for (var i = 0; i < max; i++)
                {
                    values[i] = IsDBNull(i) ? DBNull.Value : GetValue(i);
                }
    
                return max;
            }
    
            public override bool IsDBNull(int ordinal)
            {
                return GetValue(ordinal) == null;
            }
    
            public override bool NextResult()
            {
                return false;
            }
    
            public override bool Read()
            {
                return _iterator.MoveNext();
            }
        }
    

    【讨论】:

      【解决方案5】:

      我遇到了同样的问题,您无法创建 DataTable,因此只需将其转储到工作表中即可。

      Core 中缺乏对DataTable 的支持确实会迫使您创建强类型对象,然后循环遍历并将它们映射到 EPPlus 的输出。

      所以一个非常简单的例子是:

      // Get your data directly from EF,
      // or from whatever other source into a list,
      // or Enumerable of the type
      List<MyEntity> data = _whateverService.GetData();
      
      using (ExcelPackage pck = new ExcelPackage())
      {
         // Create a new sheet
         var newSheet = pck.Workbook.Worksheets.Add("Sheet 1");
         // Set the header:
         newSheet.Cells["A1"].Value = "Column 1 - Erm ID?";
         newSheet.Cells["B1"].Value = "Column 2 - Some data";
         newSheet.Cells["C1"].Value = "Column 3 - Other data";
      
        row = 2;
        foreach (var datarow in data)
        {
            // Set the data:
            newSheet.Cells["A" + row].Value = datarow.Id;
            newSheet.Cells["B" + row].Value = datarow.Column2;
            newSheet.Cells["C" + row].Value = datarow.Cilumn3;
            row++;
        }
      }
      

      因此,您正在获取可枚举的强类型对象源,您可以直接从 EF 查询、视图模型或其他任何东西中执行此操作,然后循环遍历以映射它。

      我已经使用了它,并且性能似乎 - 对最终用户来说 - 与 DataTable 方法相当。我没有检查源代码,但如果 DataTable 方法只是在内部做同样的事情并循环遍历每一行,我不会感到惊讶。

      您可以创建一个扩展方法来使用泛型传递对象列表并使用反射来正确映射它......也许我会看看这个项目,看看我是否可以贡献。

      编辑添加:

      在 .NET Core 中,从 GitHub 问题跟踪器看来,DataTable 支持在优先级列表中的位置非常低,不要指望它很快就会出现。我认为这也是一个哲学观点,因为这个概念通常是您尝试使用强类型对象。因此,过去您可以将 SQL 查询运行到 DataTable 并使用它运行...现在,您应该将该查询运行到模型中,或者通过 DbSet 直接映射到带有 Entity Framework 的表,或使用ModelBinding 并将类型传递到查询中。

      然后你有一个IQueryable&lt;T&gt;,它可以作为DataTables 的强类型替换。公平地说,这种方法在 99% 的情况下是一种有效且更好的方法……但是,有时缺少DataTables 会导致问题并需要解决!

      进一步编辑

      ADO.NET 中,您可以将datareader 转换为强类型对象列表: How can I easily convert DataReader to List<T>? 仅举一个例子。使用此列表,您可以从那里进行映射。

      如果您想/必须使用以ASP.NET Core framework 为目标的ASP.NET Core,那么您必须这样做。如果您可以使用核心项目以 Net 4.5 为目标,那么您将能够使用 System.Data 并返回 DataTables - 唯一需要注意的是您必须使用 Windows 服务器和 IIS。

      您真的需要完整的.Net Core 框架吗?你需要在linux上托管吗?如果不是,并且您确实需要 DataTables,则只需针对较旧的框架。

      【讨论】:

      • 谢谢。但我没有使用 EF - 我想坚持使用 ADO.NET。如何将其传递给 SQL Server?看起来像一个简单问题的“肮脏”解决方案......
      • ASP.NET Core 是否支持 ADO.NET?在文档中找不到它作为快速搜索...
      • EF 是基于 ADO.NET AFAIK 构建的,所以我猜是的?
      • 我现在明白了,所有的类都在那里,但没有任何东西需要DataTable...你可能仍然应该寻找强类型对象:stackoverflow.com/questions/1464883/…
      • 对这篇文章感到抱歉...您可以针对 .NET Framework 4.5 / 4.6 吗?或者您是否需要使用 Kestrel 和 linux 进行托管?如果不是,您可以设置一个使用完整 .NET Framework 4.6 并具有完整 Windows API 的 .NET Core 项目。
      【解决方案6】:

      开发者82,

      我处于同样的情况,我想使用 .net 核心,但数据表不可用,数据集很糟糕。因为您正在引用使用列表的帖子,所以我认为目标可能是以最干净的方式将 C# 列表放入数据库中。如果这是目标,那么这可能会有所帮助。

      我在各种项目中使用了位于here 的 Dapper。支持 int .netcore。下面是一个小型控制台应用程序,它采用填充的 c# 列表并将其插入数据库,然后在该表上发出 Select 以将结果写入控制台。

      using System;
      using System.Data;
      using Dapper;
      using System.Data.Common;
      using System.Data.SqlClient;
      using System.Collections.Generic;
      
      namespace TestConsoleApp
      {
          class Program
          {
              static void Main(string[] args)
              {
                  List<DataItemDTO> dataItems = GetDataItems();
      
                  var _selectSql = @"SELECT CustomerId, Name, BalanceDue from [dbo].[CustomerAccount]";
      
                  var _insertSql = @"INSERT INTO [dbo].[CustomerAccount]
                                             ([CustomerId]
                                             ,[Name]
                                             ,[BalanceDue])
                                       VALUES
                                             (@CustomerId
                                             ,@Name
                                             ,@BalanceDue)";
      
      
      
                  using (IDbConnection cn = new SqlConnection(@"Server=localhost\xxxxxxx;Database=xxxxdb;Trusted_Connection=True;"))
                  {
                      var rows = cn.Execute(_insertSql, dataItems,null,null,null );
      
                      dataItems.Clear();
      
                      var results = cn.Query<DataItemDTO>(_selectSql);
      
                      foreach (var item in results)
                      {
                          Console.WriteLine("CustomerId: {0} Name {1} BalanceDue {2}", item.CustomerId.ToString(), item.Name, item.BalanceDue.ToString());
                      }
      
      
                  }
      
                  Console.WriteLine("Press any Key");
                  Console.ReadKey();
      
              }
      
              private static List<DataItemDTO> GetDataItems()
              {
                  List<DataItemDTO> items = new List<DataItemDTO>();
      
                  items.Add(new DataItemDTO() { CustomerId = 1, Name = "abc1", BalanceDue = 11.58 });
                  items.Add(new DataItemDTO() { CustomerId = 2, Name = "abc2", BalanceDue = 21.57 });
                  items.Add(new DataItemDTO() { CustomerId = 3, Name = "abc3", BalanceDue = 31.56 });
                  items.Add(new DataItemDTO() { CustomerId = 4, Name = "abc4", BalanceDue = 41.55 });
                  items.Add(new DataItemDTO() { CustomerId = 5, Name = "abc5", BalanceDue = 51.54 });
                  items.Add(new DataItemDTO() { CustomerId = 6, Name = "abc6", BalanceDue = 61.53 });
                  items.Add(new DataItemDTO() { CustomerId = 7, Name = "abc7", BalanceDue = 71.52 });
                  items.Add(new DataItemDTO() { CustomerId = 8, Name = "abc8", BalanceDue = 81.51 });
      
                  return items;
              }
          }
      }
      

      我希望这个代码示例有所帮助。

      谢谢。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-16
        • 2021-11-08
        • 1970-01-01
        相关资源
        最近更新 更多