You can't query against the DataTable
's Rows collection, since DataRowCollection
doesn't implement IEnumerable<T>
. You need to use the AsEnumerable()
extension for DataTable
. Like so:
var results = from myRow in myDataTable.AsEnumerable()
where myRow.Field<int>("RowNo") == 1
select myRow;
And as @Keith says, you'll need to add a reference to System.Data.DataSetExtensions
AsEnumerable()
returns IEnumerable<DataRow>
. If you need to convert IEnumerable<DataRow>
to a DataTable
, use the CopyToDataTable()
extension.
Below is query with Lambda Expression,
var result = myDataTable
.AsEnumerable()
.Where(myRow => myRow.Field<int>("RowNo") == 1);
Whereas one approach is to implement the ICloneable
interface (described here, so I won't regurgitate), here's a nice deep clone object copier I found on The Code Project a while ago and incorporated it into our code.
As mentioned elsewhere, it requires your objects to be serializable.
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
public static class ObjectCopier
{
/// <summary>
/// Perform a deep copy of the object via serialization.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>A deep copy of the object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", nameof(source));
}
// Don't serialize a null object, simply return the default for that object
if (ReferenceEquals(source, null)) return default;
using var Stream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
The idea is that it serializes your object and then deserializes it into a fresh object. The benefit is that you don't have to concern yourself about cloning everything when an object gets too complex.
In case of you prefer to use the new extension methods of C# 3.0, change the method to have the following signature:
public static T Clone<T>(this T source)
{
// ...
}
Now the method call simply becomes objectBeingCloned.Clone();
.
EDIT (January 10 2015) Thought I'd revisit this, to mention I recently started using (Newtonsoft) Json to do this, it should be lighter, and avoids the overhead of [Serializable] tags. (NB @atconway has pointed out in the comments that private members are not cloned using the JSON method)
/// <summary>
/// Perform a deep Copy of the object, using Json as a serialization method. NOTE: Private members are not cloned using this method.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T CloneJson<T>(this T source)
{
// Don't serialize a null object, simply return the default for that object
if (ReferenceEquals(source, null)) return default;
// initialize inner objects individually
// for example in default constructor some list property initialized with some values,
// but in 'source' these items are cleaned -
// without ObjectCreationHandling.Replace default constructor values will be added to result
var deserializeSettings = new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace};
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
}
Best Answer
The easiest-to-understand definition of
Aggregate
is that it performs an operation on each element of the list taking into account the operations that have gone before. That is to say it performs the action on the first and second element and carries the result forward. Then it operates on the previous result and the third element and carries forward. etc.Example 1. Summing numbers
This adds
1
and2
to make3
. Then adds3
(result of previous) and3
(next element in sequence) to make6
. Then adds6
and4
to make10
.Example 2. create a csv from an array of strings
This works in much the same way. Concatenate
a
a comma andb
to makea,b
. Then concatenatesa,b
with a comma andc
to makea,b,c
. and so on.Example 3. Multiplying numbers using a seed
For completeness, there is an overload of
Aggregate
which takes a seed value.Much like the above examples, this starts with a value of
5
and multiplies it by the first element of the sequence10
giving a result of50
. This result is carried forward and multiplied by the next number in the sequence20
to give a result of1000
. This continues through the remaining 2 element of the sequence.Live examples: http://rextester.com/ZXZ64749
Docs: http://msdn.microsoft.com/en-us/library/bb548651.aspx
Addendum
Example 2, above, uses string concatenation to create a list of values separated by a comma. This is a simplistic way to explain the use of
Aggregate
which was the intention of this answer. However, if using this technique to actually create a large amount of comma separated data, it would be more appropriate to use aStringBuilder
, and this is entirely compatible withAggregate
using the seeded overload to initiate theStringBuilder
.Updated example: http://rextester.com/YZCVXV6464