converting/Casting ISingleResult - List values to DataTable without Looping - c#

I am using Linq to Sql. When My StoredProcedure Executing its result ll returned in form of IMultipleResults.
I am converting it to ISingleResults and It can be Casted as List.
So I need to Convert it to DataTable so That I can Bind it to Dataset and Pass the values to UI.
But I want such method where I can convert it without LOOP.
Please Any body Help me.
For Any Clarification Contact me.
Thanking you.

First you might want to see if you could cast your list to a BindingList, or do something like this:
BindingListX = New BindingList(Of elementX)(QueryResult.ToList())
You might be able to bind with that. If that doesn't work though here's another question: Do you want to not use a loop in your code at all, or just not see a loop in your code? It is possible to create an extension function that does the conversion:
public static class HelperFunctions
{
public static void Map<T>(this IEnumerable<T> source, Action<T> func)
{
foreach (T i in source)
func(i);
}
public static DataTable ToDataTable<T>(this IEnumerable<T> source)
{
var dt = new DataTable();
var properties = typeof(T).GetProperties();
dt.Columns.AddRange(properties.Select(x => new DataColumn(x.Name, x.PropertyType)).ToArray());
source.Select(x => dt.NewRow().ItemArray = properties.Select(y => y.GetValue(x, null)).ToArray()).Map(x => dt.Rows.Add(x));
return dt;
}
}
But as you can see, the other extension function 'Map' is nothing more than a foreach that can be used inline. If that is not what you want then I apologize and will try to come up with a different way.
It is also worth noting that I'm not sure if assigning to Item Array is the best way to populate a row so if it doesn't work then please let me know so that I may draft another version of the function.
Hope this helps!

Related

Better approach when obtaining multiple values from the same method at once

I have the following method which returns a tuple,
public Tuple<int, bool> GetStudentInformation(long stutID)
Called as,
Marks= GetStudentInformation((Id).Item1;
HasPassed= GetStudentInformation((Id).Item2;
This works fine as it is but I dont like that I call the same method twice to get item1 and item2, using Tuple is probably not the way ahead but any advice if c# has support to get two values returned over a single execution of the method?
You just need to save return value
Tuple<int, bool> info = GetStudentInformation(Id);
Marks = info.Item1;
HasPassed = info.Item2;
example of a clearer way I prefer when using tuples:
public (int data1, bool data2) GetStudentInformation(Id) {
return (123, true);
}
var studentInfo = GetStudentInformation(111);
Console.Write(studentInfo.data1);
Console.Write(studentInfo.data2);

Can I / How to Implement IEnumerable on third party object to Sort...just use LINQ?

My last two question have had down votes so my apologies in advance if this is a dumb question and a waste of your time.
I am wanting to sort a collection on a property called CreateDate so I thought I would do something like:
MyList.Sort(x => x.CreateDate)
However MyList.Sort() is not available since MyList is a Microsoft DataCollection object that does NOT implement IEnumerable.
The Microsoft DataCollection from the metadata is as such:
public class DataCollection<T> : Collection<T>
{
public void AddRange(IEnumerable<T> items);
public void AddRange(params T[] items);
public T[] ToArray();
}
So the only two options I can think of are:
Use Linq something along these lines:
var query = from xyz in self.Entities
orderby xyz.Attributes["CreateDate"]
select xyz;
or cast to a list but then I have to create a comparer and I'm not sure how to get it back without iterating over the whole thing and rebuilding the DataCollection.
List<Entity> x = self.Entities.ToList();
x.Sort(y => y.Attributes["CreateDate"], comparer)
foreach(var x in x)
{
//iterate and rebuild the DataCollection
}
Any input / critical evaluation would be appreciated
Thank You
I'm not quite sure there's enough information here to accurately diagnose the problem, but I'll give it a shot. I see two potential problems:
You're missing the reference to either System.Linq or System.Data.DataSetExtensions.
You need to cast the DataCollection to the correct type, using MyList.Cast<Entity>().OrderBy(x => x.CreateDate)
Also, note the use of .OrderBy() instead of .Sort()

Convert a DataTable to a Dictionary<T1,T2> using Generics and extension methods

I am attempting to create a Dictionary from my DataTable. Currently i do this by first creating a IList and then looping through the List and adding them to a dictionary individually specifying the Primary key property of the resulting object in the list on a case by case basis.
I was wondering if this could be done using generics.
Ive currently got the following code, which doesnt compile or work:
public static IDictionary<T1, T2> ToDictionary<T1,T2>(this DataTable table) where T2 : new()
{
IList<PropertyInfo> properties = GetPropertiesForType<T2>();
IDictionary<T1,T2> result = new Dictionary<T1,T2>();
Dictionary<string, int> propDict = GetPropertyDictionary(properties, table);
T1 PK;
foreach (var row in table.Rows)
{
var item = CreateDictItemFromRow<T2>((DataRow)row, properties, propDict);
result.Add(item. item); //not sure here
}
return result;
}
Essentially i would like to call the following:
Dictionary<int, MyDBClass> Items = DataTable.ToDictionary<int,MyDBClass>();
or
Dictionary<Int16,MyDBClass> Items = DataTable.ToDictionary<Int16, MyDBClass>();
Im assuming somewhere i need to pass the primary key property name to this function. Failing that i can safely assume the first column in my Datatable contains the primary key (although its not safe to assume it is always an int (it maybe a short or byte)).
I also understand this could quite easily be done using LINQ, but i havent got that far in C# and wish to alter existing application.
Help is appreciated.
Hope this helps.
public static class Extensions
{
public static Dictionary<TKey, TRow> TableToDictionary<TKey,TRow>(
this DataTable table,
Func<DataRow, TKey> getKey,
Func<DataRow, TRow> getRow)
{
return table
.Rows
.OfType<DataRow>()
.ToDictionary(getKey, getRow);
}
}
public static void SampleUsage()
{
DataTable t = new DataTable();
var dictionary = t.TableToDictionary(
row => row.Field<int>("ID"),
row => new {
Age = row.Field<int>("Age"),
Name = row.Field<string>("Name"),
Address = row.Field<string>("Address"),
});
}
By the way, you need to include the assembly, System.Data.DataSetExtensions.dll, to use the Field extension method.
If you have any other questions, don't hesitate to ask.
With a great help from base2, here was my completed method:
public static IDictionary<TKey, T> ToDictionary<TKey, T>(this DataTable table, Func<DataRow,TKey> getKey) where T : new()
{
IList<PropertyInfo> properties = GetPropertiesForType<T>();
IDictionary<TKey, T> result = new Dictionary<TKey, T>();
Dictionary<string, int> propDict = GetPropertyDictionary(properties, table);
foreach (var row in table.Rows)
{
var item = CreateItemFromRow<T>((DataRow)row, properties, propDict);
TKey pk = getKey((DataRow)row);
result.Add(pk,item);
}
return result;
}
which can be called like so:
IDictionary<Int16,DBClient> Clients = sql.GetDataTable("SELECT * FROM Clients").ToDictionary<Int16,DBClient>(r => r.Field<Int16>("PrimaryKeyField"));
Check out Petapoco It allows you to retrieve from the database into CLR objects and Lists. It doesn't have much overhead.
This can be achieve through reflection check out this link may help you
In this post i have tried to convert a dataset into list

Get values from an enum into a generic List

I don't know how to convert the following line from VB to C#:
Dim values As New List(Of T)(System.Enum.GetValues(GetType(T)))
My version doesn't work:
List<T> values = new List<T>(System.Enum.GetValues(typeof(T)));
The best overloaded method match for
'System.Collections.Generic.List.List(System.Collections.Generic.IEnumerable)'
has some invalid arguments
The constructor-parameter doesn't take it that way - what cast (or else) am I missing?
For clarification: It is wrapped up within the following generic method
public static void BindToEnum<T>()
{
List<T> values = new List<T>(System.Enum.GetValues(typeof(T)));
//...
}
Using LINQ:
List<T> list = System.Enum.GetValues(typeof(T))
.Cast<T>()
.ToList<T>();
Just add a .Cast<T>():
List<T> values = new List<T>(System.Enum.GetValues(typeof(T)).Cast<T>());
Based on this post, I created myself a function to do this for me; It's great in Unit Tests when you want to loop through all values of an Enum to verify something only works on certain values.
public static IEnumerable<T> GetEnumValues<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
Then I can use it like so:
var values = GetEnumValues<SomeTypeCode>();
var typesToAlwaysShow = values.Where(ScreenAdapter.AlwaysShowThisType).Select(q => (int)q).ToList();
Assert.Equal("101,102,105,205", string.Join(",", typesToAlwaysShow));

Pushing Items into stack with LINQ

How can i programatically push an array of strings into generic Stack ?
string array
string[] array=new string[]{"Liza","Ana","Sandra","Diya"};
Stack Setup
public class stack<T>
{
private int index;
List<T> list;
public stack()
{
list = new List<T>();
index=-1;
}
public void Push(T obj)
{
list.Add(obj);
index++;
}
...........
}
What is the change do i need here ?
stack<string> slist = new stack<string>();
var v = from vals in array select (p => slist.Push(p));
Error Report :
The type of the expression in the select clause is incorrect.
LINQ is a query language/framework. What you want to perform here is a modification to a collection object rather than a query (selection) - this is certainly not what LINQ is designed for (or even capable of).
What you might like to do, however, is to define an extension method that for the Stack<T> class, however. Note that it also makes sense to here to use the BCL Stack<T> type, which is exactly what you need, instead of reinventing the wheel using List<T>.
public static void PushRange<T>(this Stack<T> source, IEnumerable<T> collection)
{
foreach (var item in collection)
source.Push(item);
}
Which would then allow you do the following:
myStack.PushRange(myCollection);
And if you're not already convinced, another philosophical reason: LINQ was created to bring functional paradigms to C#/.NET, and at the core of functional programming is side-effect free code. Combining LINQ with state-modifying code would thus be quite inconsistent.
The first issue is you Push returns a void. Select is expecting a value of something.
You are just doing a loop and don't need to use link.
Since you stack is internally storing a list, you can create a list by passing it an array.
so in your case
List<string> myList = new List<string>(array);
Creats the list.
Change
public void Push(T obj)
to
public T Push(T obj)
and ignore the return values.
Disclaimer: I would not recommend mutation like this.
Try this
string[] arr = new string[]{"a","f"};
var stack = new Stack<string>();
arr.ToList().ForEach(stack.Push);
While this is "cool" is isn't any better than a for loop.
Push needs a return type for you to be able to use it in a select clause. As it is, it returns void. Your example is, I think, a horrible abuse of LINQ. Even if it worked, you'd be using a side-effect of the function in the select clause to accomplish something totally unrelated to the task that the select is intended for. If there was a "ForEach" extension, then it would be reasonable to use LINQ here, but I'd avoid it and stick with a foreach loop.
foreach (var val in array)
{
slist.Push(val);
}
This is much clearer in intent and doesn't leave one scratching their head over what you're trying to accomplish.

Categories