Convert DataTable to IEnumerableT
Nothing wrong with that implementation. You might give the yield
keyword a shot, see how you like it:
private IEnumerable<TankReading> ConvertToTankReadings(DataTable dataTable)
{
foreach (DataRow row in dataTable.Rows)
{
yield return new TankReading
{
TankReadingsID = Convert.ToInt32(row["TRReadingsID"]),
TankID = Convert.ToInt32(row["TankID"]),
ReadingDateTime = Convert.ToDateTime(row["ReadingDateTime"]),
ReadingFeet = Convert.ToInt32(row["ReadingFeet"]),
ReadingInches = Convert.ToInt32(row["ReadingInches"]),
MaterialNumber = row["MaterialNumber"].ToString(),
EnteredBy = row["EnteredBy"].ToString(),
ReadingPounds = Convert.ToDecimal(row["ReadingPounds"]),
MaterialID = Convert.ToInt32(row["MaterialID"]),
Submitted = Convert.ToBoolean(row["Submitted"]),
};
}
}
Also the AsEnumerable
isn't necessary, as List<T>
is already an IEnumerable<T>
Convert DataTable to IEnumerableT in ASP.NET Core 2.0
One of the most efficient things you can do is write the code for the iteration yourself, using a for loop instead of LINQ, just iterate over the DataTable rows and build/hydrate the IEnumerable<UserAssignmentDto>
method return value "by hand".
Since there DataTable does not implement an Enumerator in .NET Core 2.0 you will need to use a "regular" for
loop to iterate over the rows. You cannot use foreach
because DataTable has not implemented IEnumerable in .NET Core 2.0.
public static IEnumerable<UserAssignmentDto> StaffAssignmentsUsingStoredProcedure(System.Data.DataTable dataTable)
{
var retList = new List<UserAssignmentDto>();
for(int i = 0; i < dataTable.Rows.Count; i++)
{
var row = dataTable.Rows[i];
var temp = new UserAssignmentDto(){
Id = row["AssignmentNumber"],
Position = row["EsrPositionTitle"]
};
retList.Add(temp);
}
return retList;
}
Convert Datatable to generic IEnumerableT
You could create an extension method that convert it for you. Given you have properties on the query that matches the properties on your generic T
type, you could use reflection to perform it! For sample (see the comments on the code):
public static class DataTableExtensions
{
public static IEnumerable<T> ToGenericList<T>(this DataTable dataTable)
{
var properties = typeof(T).GetProperties().Where(x => x.CanWrite).ToList();
var result = new List<T>();
// loop on rows
foreach (DataRow row in dataTable.Rows)
{
// create an instance of T generic type.
var item = Activator.CreateInstance<T>();
// loop on properties and columns that matches properties
foreach (var prop in properties)
foreach (DataColumn column in dataTable.Columns)
if (prop.Name == column.ColumnName)
{
// Get the value from the datatable cell
object value = row[column.ColumnName];
// Set the value into the object
prop.SetValue(item, value);
break;
}
result.Add(item);
}
return result;
}
}
And given you have a model like this:
public class Student
{
public int Id { get; set; }
public string Code { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// other possible properties
}
You can use the extension method like this:
protected async Task<IEnumerable<T>> QuerySqlCmdReadRows<T>(string sqlCommand)
{
using (var con = new SqlConnection(Connection.ToString()))
{
con.Open();
using (var cmd = con.CreateCommand())
{
cmd.CommandText = sqlCommand;
DataTable dtResult = new DataTable();
using (var reader = await cmd.ExecuteReaderAsync())
dtResult.Load(reader);
return dtResult.ToGenericList<T>();
}
}
}
// just and sample
var students = QuerySqlCmdReadRows<Students>("select Id, Code, FirstName, LastName from Students");
Converting Datatable to ienumerableanonymous?
var results = from row in dataTable.AsEnumerable()
select new {
First = row.Field<string>("First"),
Last = row.Field<string>("Second")
};
You'll need System.Data.DataSetExtensions
.
Convert datatable to IEnumerableT to pass to ResultT(IEnumerableT data);
I ended up using Linq to convert the datatable into an array of anonymous objects.
Dim objs = From row In dt Select New With {
.Id = row.Field(Of Integer)("Id"),
.Count = row.Field(Of Integer)("Count")
}
Then I created a generic function to use type inference to get the anonymous object array into the Result object's constructor
Private Function GetResult(Of T)(ByVal data As IEnumerable(Of T)) As Result(Of T)
Return New Result(Of T)(Nothing, data)
End Function
Called using Dim result = GetResult(objs)
Error Converting Datatable to IEnumerable
You are getting that error because dtRepSummary.AsEnumerable()
returns IEnumerable<DataRow>
but you have the return type as IEnumerable<Landing>
, you can use Select to project your type like this:-
return dtRepSummary.AsEnumerable().Select(x => new Landing
{
Reportid = x.Field<int>("Reportid"),
Reportdate = x.Field<string>("Reportdate"),
..and so on
};
An efficient way to convert from IEnumerableT to DataTable
Instead of going through a DataTable, I would implement an IDataReader for your collection and feed that to SqlBulkCopy. If done correctly, and using a lazy IEnumerable, it would be much faster, and use much less memory than the datatable route. Mark Gravell has already written such a library for converting IEnumerables to an IDataReader, and I would recommend you check that out before rolling your own.
FastMember can be found on NuGet here: https://www.nuget.org/packages/FastMember/
with the original source found here: https://code.google.com/p/fast-member/ with an example in this thread here: SqlBulkCopy from a List<>
UPDATE:
You may also need to change your command timeout, and set the batch size on the sqlbulkcopy, like this:
using (SqlCommand cmd = new SqlCommand(modelManager.GetInsertSproc(), sqlconn) {
CommandType = CommandType.StoredProcedure, CommandTimeout=300 })
and
bcp.BatchSize = 100000;
Related Topics
Closures Behaving Differently in for and Foreach Loops
Calculating Hmacsha256 Using C# to Match Payment Provider Example
JSON Deserialization - Map Array Indices to Properties with JSON.Net
Wcf - Design Parameter Decision
Where Is Httpcontent.Readasasync
Best Way to Check for Nullable Bool in a Condition Expression (If ...)
Use the Dynamic Keyword/.Net 4.6 Feature in Unity
How to Use Linq Distinct() with Multiple Fields
How to Create an Odbc Dsn Entry Using C#
How to Create a File and Any Folders, If the Folders Don't Exist
Digital Signature in C# Without Using Bouncycastle
Visual Studio Installer > How to Launch App at End of Installer
How to Use Custom Authorize Attribute for Roles as Well as a Specific User
Is There a Complete Iequatable Implementation Reference
Get All Associate/Composite Objects Inside an Object (In Abstract Way)
How to Keep Single SQL Server Connection Instance Open for Multiple Request in C#
Why I'm Getting Cs1012: "Too Many Characters in Character Literal" and Cs0019