I am using entityframework. I had two records which are retrieved from table using 'id' which is a primary key. Now i want to compare these two table records data and display the old value and new value in my view. Now my question is how to compare two records... There are almost 20 properties in my table from which i retrieve the data. We have to compare each and every property or is there are any best method... Can any one please help me to find the solution..
public bool Equals<T>(T first, T second)
{
var f = new List<T>() {first};
var s = new List<T>() {second};
PropertyInfo[] propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Static);
foreach (PropertyInfo propertyInfo in propertyInfos)
{
if (f.Select(x => propertyInfo.Name).FirstOrDefault() != s.Select(x => propertyInfo.Name).FirstOrDefault())
return false;
}
return true;
}
Changed to Equals < T > (T first, T second) as Kim R recommended
Try it :) I haven't tested it
Related
var result=(from refridgerators in context.A
group refridgerators by new { refridgerators.Id, refridgerators.Name } into gr
select new DAO<String>
{
Key = gr.Key.Name,
Count = gr.Count()
}).OrderByDescending(k => k.Count).Take(numberOfRecords).ToList();
This is my linq to sql query this is working perfectly fine.
this shows top 5 records (sorted by their count) if i pass numberOfRecords =5.
now my problem is i don`t want to modify query. so what should i do in above query to show all records. This is in relation with my requirement i want to use same query to show all refridgerators and Top 5 , top 10 refridgerators.
I am not sure if it is possible using LINQ. but i guess there must be something related to this.
I would simply don't add the Take to the query but to the code where you consume this query.
So for example:
public static IEnumerable<DAO> GetRefrigerators()
{
var query = from refridgerators in context.A
group refridgerators by new { refridgerators.Id, refridgerators.Name } into gr
select new DAO<String>
{
Key = gr.Key.Name,
Count = gr.Count()
};
return query.OrderByDescending(k => k.Count);
}
Now you can either use:
var refrigerators = GetRefrigerators().Take(5).ToList();
or
var refrigerators = GetRefrigerators().Take(10).ToList();
or
var refrigerators = GetRefrigerators().ToList();
I'd make numberOfRecords a int? and if the value is null you should not call Take(numberOfRecords)
var result = (from refridgerators in context.A
group refridgerators by new { refridgerators.Id, refridgerators.Name } into gr
select new DAO<String>
{
Key = gr.Key.Name,
Count = gr.Count()
}).OrderByDescending(k => k.Count);
if(numberOfRecords.HasValue)
result = result.Take(numberOfRecords.Value);
return result.ToList();
I know it changes your query a little bit but I believe it is pretty acceptable, adding a numberOfRecords of a super high value adds an overheard to your query which isn't useful in your case.
So this post is very old, I know, but my solution is not provided (maybe someone wants to achieve the same after 2 years, like me):
You could create your own extension-method that also works with linq 2 sql. Example:
public static class LinqExtensions
{
public static IEnumerable<TResult> TakeIfNotNull<TResult>(this IEnumerable<TResult> source, int? count)
{
return !count.HasValue ? source : source.Take(count.Value);
}
}
this takes an int? instead of int and returns either the source-enumerable if count is null else it returns the result of default Take-method.
So you could write like:
.OrderByDescending(k => k.Count).TakeIfNotNull(numberOfRecords).ToList();
if numberOfCounts is null, it'll take all records.
As the right solution has already been posted by Tim, still I want your attention to the simpler solution, if suits to your requirement.
Add one more if condition at the top of this query.
if(allRecordRequired)
{
numberOfRecords = 2000000;
}
Leave your query as it is.
Pass a huge number to your method.A number that is equal (at least) or bigger than the items count.That should give you all records.
There are many tables in the database that are used as "lookup" tables. All the tables have the same structure, other than the ID column name.
I have found that I can use reflection to open a table and enumerate through the records. The method takes a string (tableName).
Uri serviceUri = new Uri("http://localhost/MyDataService/WcfDataService.svc");
var context = new MyEntities(serviceUri);
var eTable = typeof(MyEntities).GetProperty(tableName).GetValue(context, null) as IEnumerable<object>
foreach (object o in eTable)
...
This works fine, but I want to add a WHERE clause to the query. For example, where InactiveDate == null.
Can I do this? I have been unable to figure this one out.
How about this?
var eTable = (typeof(MyEntities).GetProperty(tableName).GetValue(context, null) as IEnumerable<object>).Where(obj => obj.GetType().GetProperty("InactiveDate").GetValue(obj) == null);
foreach (object o in eTable)
I would suggest to use generics and maybe an interface over reflection.
public function Xyz<TEntity>(Func<MyEntities, IDbSet<TEntity>> dbSetGetter, Expression<Func<TEntity, Boolean>> filter)
{
var serviceUri = new Uri("http://localhost/MyDataService/WcfDataService.svc");
using (var context = new MyEntities(serviceUri))
{
foreach (var entity in dbSetGetter(context).Where(filter))
{
DoSomethingWith(entity);
}
}
}
Usage would be like this
Xyz(context => context.Foo, foo => foo.Bar == 42);
assuming you have an entity Foo with an integer property Bar. The obvious difference to your code is that you have to know the entity type a compile time and I am not sure if you know it then.
I have a SQL Database which I imported as a ADO.NET Entity Data Model. I then populate a DataGridView using Linq. I extended two of the tables with extra columns that are calculated from other tables. For instance, I have a table Orders that has fields OrderNumber, DateApproved and RequestorID and so on. I also have a table that is the OrderDetails with Fields like SKU, OrderNUmber and QuanityOrdered. I coded a new column IsBackOrdered for the Orders Table that calculates if any Item(SKU) from the OrderDetails is backordered.
When I bound the table Orders to the DataGridView.DataSource everything works as expected. I was then directed to create a search filter for the table.
I tried to map BindingSource to the Linq query but BindingSource is expecting a DataTable. I found a neat little method that converts Linq ResultSet to a DataTable (Code below) however it barfs on my custom fields (Columns) at this line: dr[pi.Name] = pi.GetValue(rec, null) ?? DBNull.Value;
Thanks in advance for any of your view or helpful insights you would care to offer.
public static DataTable LinqToDataTable<T>(IEnumerable<T> varlist)
{
var dtReturn = new DataTable();
// column names
PropertyInfo[] oProps = null;
if (varlist == null)
return dtReturn;
foreach (T rec in varlist)
{
// Use reflection to get property names, to create table, Only first time, others will follow
if (oProps == null)
{
oProps = rec.GetType().GetProperties();
foreach (PropertyInfo pi in oProps)
{
Type colType = pi.PropertyType;
if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
colType = colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
}
}
DataRow dr = dtReturn.NewRow();
foreach (PropertyInfo pi in oProps)
{
dr[pi.Name] = pi.GetValue(rec, null) ?? DBNull.Value;
}
dtReturn.Rows.Add(dr);
}
return dtReturn;
}
DataSource property of the BindingSource doesn't expect DataTable. It's of type object, so you may use any list as data source. But in this case to be able to filter it you should either implement IBindingListView or use BindingList. The second case is easier of course. Take a look here for more information.
Very frustrated here ...
I can usually find an answer of some kind to complex issues in .Net somewhere on the net, but this one eludes me.
I'm in a scenario where I have to convert the result of a LINQ to Entity query into a DataSet so the data can then be processed by existing business logic, and I can't find a single working solution out ther for this.
I've tried basic approaches like the EntityCommand generating a reader, but this one does not work because DataTable.Load() thorws an excpetion (the reader generated by EntityCommand does not support GetSchemaTable() ).
I've also tried more [supposedly] friendly approaches like Entity to IDataReader(http://l2edatareaderadapter.codeplex.com/), but this one throws exceptions, has very little docs, and hasn't been touched since 2008.
Another approach I found is here (http://blogs.msdn.com/b/alexj/archive/2007/11/27/hydrating-an-entitydatareader-into-a-datatable-part-1.aspx), but does not have a working copy of the code; only snippets.
I find it hard to believe that first of all MS would not have offered this backwards-compatibility item out of the box, and second, that it would not have been created by the community either.
I'm willing to look at commercial solutions as well if any are available.
Thx!
You can convert the result into a list and use the following to convert the list to a datatable.
public DataTable ConvertToDataTable<T>(IList<T> data)
{
PropertyDescriptorCollection properties =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
foreach (T item in data)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
return table;
}
http://social.msdn.microsoft.com/Forums/br/csharpgeneral/thread/6ffcb247-77fb-40b4-bcba-08ba377ab9db
Hope this helps
Preetam
This might not be the greatest solution, but if your scenario have only one or two table that you need to add to the DataSet, why not build them directly manually.
var result = db.YourTable; // get your Linq To Entities result.
DataSet ds = new DataSet();
DataTable tbl = new DataTable();
tbl.Columns.Add("col1", typeof(string));
tbl.Columns.Add("col2", typeof(int));
foreach (var r in result)
{
var row = tbl.NewRow();
row[0] = r.Col1;
row[1] = r.Col2;
tbl.Rows.Add(r);
}
ds.Tables.Add(tbl);
The Col1 and Col2 comes from your Linq To Entity objects, you can create all the table you need like this and return your DataSet.
This is a flexible code and should handle most of your needs:
public DataTable LINQToDataTable<T>(IEnumerable<T> varlist)
{
DataTable dtReturn = new DataTable();
// column names
PropertyInfo[] oProps = null;
if (varlist == null) return dtReturn;
foreach (T rec in varlist)
{
// Use reflection to get property names, to create table, Only first time, others will follow
if (oProps == null)
{
oProps = ((Type)rec.GetType()).GetProperties();
foreach (PropertyInfo pi in oProps)
{
Type colType = pi.PropertyType;
if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
colType = colType.GetGenericArguments()[0];
}
dtReturn.Columns.Add(new DataColumn(pi.Name, colType));
}
}
DataRow dr = dtReturn.NewRow();
foreach (PropertyInfo pi in oProps)
{
dr[pi.Name] = pi.GetValue(rec, null) == null ? DBNull.Value : pi.GetValue
(rec, null);
}
dtReturn.Rows.Add(dr);
}
return dtReturn;
}
I am currently working on a project where i need to show row data in gridview columns, so for example, if my data is in the following form.
Username Jack
Phone 2222222
Email jack#gmail.com
and i want to show this data as per columns in gridview as below
Username Phone Email
jack 2222222 jack#gmail.com
How would i do it? specially through LINQ, like can i query DB in any way so it return data in the form that i want?
You want to Transpose your data. Here's an extension method you can use, shamelessly stolen from here:
public static IEnumerable<IEnumerable<T>> Transpose<T>(this IEnumerable<IEnumerable<T>> values)
{
if (values.Count() == 0)
return values;
if (values.First().Count() == 0)
return Transpose(values.Skip(1));
var x = values.First().First();
var xs = values.First().Skip(1);
var xss = values.Skip(1);
return
new[] {new[] {x}
.Concat(xss.Select(ht => ht.First()))}
.Concat(new[] { xs }
.Concat(xss.Select(ht => ht.Skip(1)))
.Transpose());
}