What's problem on linq databinding - linq

<dx:ASPxGridView ID="ASPxGridView1" runat="server" AutoGenerateColumns="False"
KeyFieldName="CategoryID">
<SettingsEditing Mode="Inline" />
<Columns>
<dx:GridViewCommandColumn VisibleIndex="0">
<EditButton Visible="True"></EditButton>
<NewButton Visible="True"></NewButton>
<DeleteButton Visible="True"></DeleteButton>
</dx:GridViewCommandColumn>
<dx:GridViewDataTextColumn Caption="CategoryID" FieldName="CategoryID"
VisibleIndex="1">
</dx:GridViewDataTextColumn>
<dx:GridViewDataTextColumn Caption="CategoryName" FieldName="CategoryName"
VisibleIndex="2">
</dx:GridViewDataTextColumn>
<dx:GridViewDataTextColumn Caption="Description" FieldName="Description"
VisibleIndex="3">
</dx:GridViewDataTextColumn>
</Columns>
</dx:ASPxGridView>
C# syntax:
NorthwindDataContext db = new NorthwindDataContext();
var lresult = (db.Categories
.Select(p => new { p.CategoryID, p.CategoryName, p.Description}));
ASPxGridView1.DataSource = lresult;
ASPxGridView1.DataBind();
If you run the code, you get a gridview which is filled by NorthWind Categories table. If you click on command button of grid whose are on left side, you get insert/update field, but you have not access to give input. They are gone to read only mode.
If I replace the above C# syntax with below
NorthwindDataContext db = new NorthwindDataContext();
var lresult = (db.Categories);
ASPxGridView1.DataSource = lresult;
ASPxGridView1.DataBind();
then it works fine. Now you can work with command button with out facing any problem.
I want to know what the problem is, why the first syntax does not work. Maybe you say
Anonymous types are class types that consist of one or more public read-only properties. But when you need to join more than one table and need to select several fields not all than what you do. Hope you not say linq is fail to do that or Don't think it is possible. Hope there must be any technique or else something to bind control with Anonymous type. Plz show some syntax .

The problem is that the result set is collection of Anonymous type as you supposed and the grid doesn't know how to treat it. What you have to do is to use RowInserting and RowUpdating events of the grid.
Here is an example of how I use DevExpress grid with NHibernate:
protected void gridAgentGroups_RowInserting(object sender, DevExpress.Web.Data.ASPxDataInsertingEventArgs e)
{
ASPxGridView currentGrid = sender as ASPxGridView;
var currentAgentGroup = new AgentGroup();
if (e.NewValues.Contains("Name"))
{
var newValue = (string)e.NewValues["Name"];
currentAgentGroup.Name = newValue;
}
if (e.NewValues.Contains("PhysicalAddress"))
{
var newValue = (string)e.NewValues["PhysicalAddress"];
currentAgentGroup.PhysicalAddress = newValue;
}
AgentGroupsDataAccess.SaveAgentGroup(currentAgentGroup);
e.Cancel = true;
currentGrid.CancelEdit();
currentGrid.DataBind();
}
protected void gridAgentGroups_RowUpdating(object sender, DevExpress.Web.Data.ASPxDataUpdatingEventArgs e)
{
ASPxGridView currentGrid = sender as ASPxGridView;
int currentAgentGroupId = (int)((AgentGroup)currentGrid.GetRow(currentGrid.EditingRowVisibleIndex)).Id;
var currentAgentGroup = AgentGroups.Where(ag => ag.Id == currentAgentGroupId).FirstOrDefault();
if (e.NewValues.Contains("Name"))
{
var newValue = (string)e.NewValues["Name"];
currentAgentGroup.Name = newValue;
}
if (e.NewValues.Contains("PhysicalAddress"))
{
var newValue = (string)e.NewValues["PhysicalAddress"];
currentAgentGroup.PhysicalAddress = newValue;
}
AgentGroupsDataAccess.SaveAgentGroup(currentAgentGroup);
e.Cancel = true;
currentGrid.CancelEdit();
currentGrid.DataBind();
}
I hope this will help.

Just a wild guess - you're binding your data to the grid using field names - yet, your anonymous type doesn't really have any field names.
Does it make any difference if you try this code:
NorthwindDataContext db = new NorthwindDataContext();
var lresult = (db.Categories
.Select(p => new { CategoryID = p.CategoryID,
CategoryName = p.CategoryName,
Description = p.Description}));
ASPxGridView1.DataSource = lresult;
ASPxGridView1.DataBind();
Again - I don't have the means to test this right now, it's just a gut feeling..... try it - does that help at all??

You actually can bind with anonymous type as you see the already filled rows. But: the grid itself cannot know how you build the query and what to add additionally to the visible columns (if there are valid default values).
As you use Developer Express' grid you have the option to provide your own update / edit form and handle everything needed on your own.

Related

How to create separate DetailTable on each row in a RadGrid?

I have a telerik radgrid where columns and detail tables are declared like:
<telerik:RadGrid>
<Columns>
<telerik:GridBoundColumn/>
<telerik:GridBoundColumn/>
</Columns>
<DetailTables>
<telerik:GridTableView
<Columns>
<telerik:GridBoundColumn/>
<telerik:GridBoundColumn/>
</Columns>
</telerik:GridTableView
</DetailTables>
</telerik:RadGrid>
Which gives a nested grid like this:
Now, what I want is to be able to specify a detail table (those sub tables) per row, programmatically.
(I cannot be sure that the columns for the nested table that comes up when I expand the line fgvbvb will be the same as the columns when expanding the line xcxcv).
I have tried, without luck in the OnDataBound handler of the radgrid (in which I omitted <DetailTables>) to access the data structure for nested tables like this:
protected void OnRadGridDataBound(object sender, EventArgs e)
{
foreach (GridDataItem item in grdActivitiesToCopy.MasterTableView.Items)
{
var dg = item.ChildItem.NestedTableViews[0];
}
}
This will overindex the array NestedTableViews because it is empty. Also, item.ChildItem.NestedTableViews has no setter.
How do I populate each row with a detail table one by one manually?
According to Telerik:
RadGrid does not support mixing declarative grid columns with grid
columns added dynamically at runtime. You should either create all the
columns in the grid programmatically, or else define them all in the
ASPX file. When creating Detail tables, it should be created in the
PageInit event.
Creating a Hierarchical Grid Programmatically:
You should follow these basic steps in order to create hierarchical
RadGrid programmatically in the code-behind (having a data source
control for data content generation):
Create the grid dynamically in the Page_Init handler of the page by
calling its constructor.
Specify the preferred settings for your grid instance through its
properties.
Create columns for the grid dynamically. Keep in mind that you have to
first set their properties and then add them to the
MasterTableView/GridTableView collection (discussed in the first
paragraph of this same topic). Thus, their ViewState will be properly
persisted (as LoadViewState is raised after the Init event of the
page).
Set the proper ParentTableRelations for the GridTableViews (along with
their MasterKeyField and DetailKeyField attributes) and DataKeyNames
for the MasterTableView/GridTableViews in the code-behind of the page.
Assign data sources (through the DataSourceID attribute) for each
table in the grid hierarchy.If you do not want to use declarative
relations, generate the data in the NeedDataSource/DetailTableDataBind
handlers of the grid. On DetailTableDataBind you can determine which
data source should be related to the currently bound GridTableView by
checking its Name/DataSourceID property. Here, the Name property must
have a unique value for each detail table (this value has to be
defined previously by the developer) and the DataSourceID is the ID of
the DataSource control responsible for the corresponding detail table
content generation.
Code Sample:
RadGrid RadGrid1 = new RadGrid();
RadGrid1.DataSourceID = "SqlDataSource1";
RadGrid1.MasterTableView.DataKeyNames = new string[] { "CustomerID" };
RadGrid1.Skin = "Default";
RadGrid1.Width = Unit.Percentage(100);
RadGrid1.PageSize = 15;
RadGrid1.AllowPaging = true;
RadGrid1.AutoGenerateColumns = false;
//Add columns
GridBoundColumn boundColumn;
boundColumn = new GridBoundColumn();
boundColumn.DataField = "CustomerID";
boundColumn.HeaderText = "CustomerID";
RadGrid1.MasterTableView.Columns.Add(boundColumn);
boundColumn = new GridBoundColumn();
boundColumn.DataField = "ContactName";
boundColumn.HeaderText = "Contact Name";
RadGrid1.MasterTableView.Columns.Add(boundColumn);
//Detail table - Orders (II in hierarchy level)
GridTableView tableViewOrders = new GridTableView(RadGrid1);
tableViewOrders.DataSourceID = "SqlDataSource2";
tableViewOrders.DataKeyNames = new string[] { "OrderID" };
GridRelationFields relationFields = new GridRelationFields();
relationFields.MasterKeyField = "CustomerID";
relationFields.DetailKeyField = "CustomerID";
tableViewOrders.ParentTableRelation.Add(relationFields);
RadGrid1.MasterTableView.DetailTables.Add(tableViewOrders);
Please refer to this help article for more details:
http://docs.telerik.com/devtools/aspnet-ajax/controls/grid/defining-structure/creating-a-radgrid-programmatically#creating-a-hierarchical-grid-programmatically
First of all , because of the life cicle of a asp page. You can't access to a event on a detail table.
If you need to access detail tables , items etc ..
You need to add an method to the PreRender in the MasterTableView like this:
<MasterTableView DataSourceID="myDataSource"
AllowMultiColumnSorting="True"
DataKeyNames="Key1,Key2,KeyN"
HierarchyDefaultExpanded="True"
OnPreRender="Unnamed_PreRender" >
The method will recursively iterate through the grid.
The way you do it can change depending on your HieararchyLoadMode.
So this is my way to do it, easiest way exist if you are on Client or Serverbind mode.
Traversing and load mode by the telerik doc .
I'm pretty sure you don't want to :
"populate each row with a detail table one by one manually"
You want to have Multiple table at a Sub Level in your grid and display the rigth one programmatically.
And this is can be done in two easy step:
1/. Create every Detail table in your apsx page.
Please refer to this documentation for more information :
Several tables at a level
2/. Handle the display:
protected void Unnamed_PreRender(object sender, EventArgs e)
{
if (!IsPostBack) myControler(MASTERGRID.MasterTableView);
}
private void myControler(GridTableView gridTableView)
{
GridItem[] nestedViewItems = gridTableView.GetItems(GridItemType.NestedView);
foreach (GridNestedViewItem nestedViewItem in nestedViewItems)
{
foreach (GridTableView nestedView in nestedViewItem.NestedTableViews)
{
if (nestedView.Name == "mytable12" && nestedView.Items.Count == 0)
{ HideExpandColumn(nestedView, nestedView.ParentItem["ExpandColumn"]); }
else if (nestedView.Name == "mytable23")
{
if (nestedView.Items.Count == 0)//
HideExpandColumn(nestedView, nestedView.ParentItem["ExpandColumn"]);
else
{ }
}
if (nestedView.HasDetailTables)
{ myControler(nestedView); }
}
}
}
private void HideExpandColumn(GridTableView _GNVI, TableCell _cell)
{
if (_cell.Controls.Count > 0)
{
_cell.Controls[0].Visible = false;
_cell.Text = " ";
}
_GNVI.Visible = false;
}
You can hide a detail table using :
HideExpandColumn(nestedView, nestedView.ParentItem["ExpandColumn"]);
Or you can hide the parent of the detail table you tested using the detail table that is in param of the controler :
HideExpandColumn(gridTableView, nestedView.ParentItem["ExpandColumn"]);
HideExpandColumn will hide the expand control that stay sometimes even if you hide th detail table.
Bonus: If you need to access to a control in a detail table.
You can use this:
public static class ControlExtensions
{
public static Control FindIt(this Control control, string id)
{
if (control == null) return null;
Control ctrl = control.FindControl(id);
if (ctrl == null)
{
foreach (Control child in control.Controls)
{
ctrl = FindIt(child, id);
if (ctrl != null) break;
}
}
return ctrl;
}
}
Calling it in your controler like this :
else if (nestedView.Name == "DetailPV")
{
if (nestedView.Items.Count == 0)
HideExpandColumn(gridTableView, nestedView.ParentItem["ExpandColumn"]);
else
{
RadLabel ctrl = (RadLabel)this.FindIt("RadLabel11");
ctrl.Text += "<b>" + nestedView.Items.Count.ToString() + "</b>";
}

Explicit construction of entity type in query is not allowed [duplicate]

Using Linq commands and Linq To SQL datacontext, Im trying to instance an Entity called "Produccion" from my datacontext in this way:
Demo.View.Data.PRODUCCION pocoProduccion =
(
from m in db.MEDICOXPROMOTORs
join a in db.ATENCIONs on m.cmp equals a.cmp
join e in db.EXAMENXATENCIONs on a.numeroatencion equals e.numeroatencion
join c in db.CITAs on e.numerocita equals c.numerocita
where e.codigo == codigoExamenxAtencion
select new Demo.View.Data.PRODUCCION
{
cmp = a.cmp,
bonificacion = comi,
valorventa = precioEstudio,
codigoestudio = lblCodigoEstudio.Content.ToString(),
codigopaciente = Convert.ToInt32(lblCodigoPaciente.Content.ToString()),
codigoproduccion = Convert.ToInt32(lblNroInforme.Content.ToString()),
codigopromotor = m.codigopromotor,
fecha = Convert.ToDateTime(DateTime.Today.ToShortDateString()),
numeroinforme = Convert.ToInt32(lblNroInforme.Content.ToString()),
revisado = false,
codigozona = (c.codigozona.Value == null ? Convert.ToInt32(c.codigozona) : 0),
codigoclinica = Convert.ToInt32(c.codigoclinica),
codigoclase = e.codigoclase,
}
).FirstOrDefault();
While executing the above code, I'm getting the following error that the stack trace is included:
System.NotSupportedException was caught
Message="The explicit construction of the entity type 'Demo.View.Data.PRODUCCION' in a query is not allowed."
Source="System.Data.Linq"
StackTrace:
en System.Data.Linq.SqlClient.QueryConverter.VisitMemberInit(MemberInitExpression init)
en System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
en System.Data.Linq.SqlClient.QueryConverter.Visit(Expression node)
en System.Data.Linq.SqlClient.QueryConverter.VisitSelect(Expression sequence, LambdaExpression selector)
en System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc)
en System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc)
en System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
en System.Data.Linq.SqlClient.QueryConverter.Visit(Expression node)
en System.Data.Linq.SqlClient.QueryConverter.VisitFirst(Expression sequence, LambdaExpression lambda, Boolean isFirst)
en System.Data.Linq.SqlClient.QueryConverter.VisitSequenceOperatorCall(MethodCallExpression mc)
en System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc)
en System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)
en System.Data.Linq.SqlClient.QueryConverter.ConvertOuter(Expression node)
en System.Data.Linq.SqlClient.SqlProvider.BuildQuery(Expression query, SqlNodeAnnotations annotations)
en System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)
en System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute[S](Expression expression)
en System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
en Demo.View.InformeMedico.realizarProduccionInforme(Int32 codigoExamenxAtencion, Double precioEstudio, Int32 comi) en D:\cs_InformeMedico\app\InformeMedico.xaml.cs:línea 602
en Demo.View.InformeMedico.UpdateEstadoEstudio(Int32 codigo, Char state) en D:\cs_InformeMedico\app\InformeMedico.xaml.cs:línea 591
en Demo.View.InformeMedico.btnGuardar_Click(Object sender, RoutedEventArgs e) en D:\cs_InformeMedico\app\InformeMedico.xaml.cs:línea 683
InnerException:
Is that now allowed in LINQ2SQL?
Entities can be created outside of queries and inserted into the data store using a DataContext. You can then retrieve them using queries. However, you can't create entities as part of a query.
I am finding this limitation to be very annoying, and going against the common trend of not using SELECT * in queries.
Still with c# anonymous types there is a workaround, by fetching the objects into an anonymous type, and then copy it over into the correct type.
For example:
var q = from emp in employees where emp.ID !=0
select new {Name = emp.First + " " + emp.Last, EmployeeId = emp.ID }
var r = q.ToList();
List<User> users = new List<User>(r.Select(new User
{
Name = r.Name,
EmployeeId = r.EmployeeId
}));
And in the case when we deal with a single value (as in the situation described in the question) it is even easier, and we just need to copy directly the values:
var q = from emp in employees where emp.ID !=0
select new { Name = emp.First + " " + emp.Last, EmployeeId = emp.ID }
var r = q.FirstOrDefault();
User user = new User { Name = r.Name, EmployeeId = r.ID };
If the name of the properties match the database columns we can do it even simpler in the query, by doing select
var q = from emp in employees where emp.ID !=0
select new { emp.First, emp.Last, emp.ID }
One might go ahead and write a lambda expression that can copy automatically based on the property name, without needing to specify the values explictly.
Here's another workaround:
Make a class that derives from your LINQ to SQL class. I'm assuming that the L2S class that you want to return is Order:
internal class OrderView : Order { }
Now write the query this way:
var query = from o in db.Order
select new OrderView // instead of Order
{
OrderID = o.OrderID,
OrderDate = o.OrderDate,
// etc.
};
Cast the result back into Order, like this:
return query.Cast<Order>().ToList(); // or .FirstOrDefault()
(or use something more sensible, like BLToolkit / LINQ to DB)
Note: I haven't tested to see if tracking works or not; it works to retrieve data, which is what I needed.
I have found that if you do a .ToList() on the query before trying to contruct new objects it works
I just ran into the same issue.
I found a very easy solution.
var a = att as Attachment;
Func<Culture, AttachmentCulture> make =
c => new AttachmentCulture { Culture = c };
var culs = from c in dc.Cultures
let ac = c.AttachmentCultures.SingleOrDefault(
x => x.Attachment == a)
select ac == null ? make(c) : ac;
return culs;
I construct an anonymous type, use IEnumerable (which preserves deferred execution), and then re-consruct the datacontext object. Both Employee and Manager are datacontext objects:
var q = dc.Employees.Where(p => p.IsManager == 1)
.Select(p => new { Id = p.Id, Name = p.Name })
.AsEnumerable()
.Select(item => new Manager() { Id = item.Id, Name = item.Name });
Within the book "70-515 Web Applications Development with Microsoft .NET Framework 4 - Self paced training kit", page 638 has the following example to output results to a strongly typed object:
IEnumerable<User> users = from emp in employees where emp.ID !=0
select new User
{
Name = emp.First + " " + emp.Last,
EmployeeId = emp.ID
}
Mark Pecks advice appears to contradict this book - however, for me this example still displays the above error as well, leaving me somewhat confused. Is this linked to version differences? Any suggestions welcome.
I found another workaround for the problem that even lets you retain your result as IQueryale, so it doesn't actually execute the query until you want it to be executed (like it would with the ToList() method).
So linq doesn't allow you to create an entity as a part of query? You can shift that task to the database itself and create a function that will grab the data you want. After you import the function to your data context, you just need to set the result type to the one you want.
I found out about this when I had to write a piece of code that would produce a IQueryable<T> in which the items don't actually exist in the table containing T.
pbz posted a work around by creating a View class inherited from an entity class that you could be working with. I'm working with a dbml model of a table that has > 200 columns. When I try and return the whole table I get "Root Element missing" errors. I couldn't find anyone who wanted to deal with my particular issue so I was looking at rewriting my entire approach. Just creating a view class for the entitiy class worked in my case.
As pbz suggests : Create a view class that inherits from your entity class. For me this is tbCamp so :
internal class tbCampView : tbCamp
{
}
Then use the view class in your query :
using (var dc = ConnectionClass.Connect(Dev))
{
var camps = dc.tbCamps.Select(s => new tbCampView
{
active = s.active,
idCamp = s.idCamp,
campName = s.campName
});
SmartTableViewer(camps, dg1);
}
private void SmartTableViewer<T>(IEnumerable<T> allRecords)
{
// Build sorted rows back into new table
var table = new DataTable();
// Create columns based on type
if (allRecords is IEnumerable<tbCamp> tbCampRecords)
{
// Get the columns you want
table.Columns.Add("idCamp");
table.Columns.Add("campName");
foreach (var record in tbCampRecords)
{
// Make a new row
var r = table.NewRow();
// Add the contents to each column of the row
r["idCamp"] = record.idCamp;
r["campName"] = record.campName;
// Add the row to the table.
table.Rows.Add(r);
}
}
else
{
MessageBox.Show("Unhandled type. Add support for new data type in SmartTableViewer()");
return;
}
// Update table in grid
dg1.DataSource = table.DefaultView;
}
Here is what happens when you try and create an entity class object in the query.
I didn't want to have to use an anonymous type if I could help it because I wanted the type to be tbCamp. Since tbCampView is of type tbCamp the is operator works well. see Brian Hasden's answer Passing a generic List<> in C#
I'm surprised this is even an issue but with larger tables I run into this error so I thought I would just show it here :
When trying to read this table into memory I get the following error. There are < 2000 rows but the columns are > 200 for each. I don't know if that is an issue or not.
If I just want a few columns I need to create a custom class and handle that which isn't that big of a pain. With the approach pbz provided I don't have to worry about it.
Here is the entire project in case it helps someone.
public partial class Form1 : Form
{
private const bool Dev = true;
public Form1()
{
InitializeComponent();
}
private void btnGetAllCamps_Click(object sender, EventArgs e)
{
using (var dc = ConnectionClass.Connect(Dev))
{
IQueryable<tbCampView> camps = dc.tbCamps.Select(s => new tbCampView
{
// Project columns as needed.
active = s.active,
idCamp = s.idCamp,
campName = s.campName
});
// pass in as a
SmartTableViewer(camps);
}
}
private void SmartTableViewer<T>(IEnumerable<T> allRecords)
{
// Build sorted rows back into new table
var table = new DataTable();
// Create columns based on type
if (allRecords is IEnumerable<tbCamp> tbCampRecords)
{
// Get the columns you want
table.Columns.Add("idCamp");
table.Columns.Add("campName");
foreach (var record in tbCampRecords)
{
//var newRecord = record;
// Make a new row
var r = table.NewRow();
// Add the contents to each column of the row
r["idCamp"] = record.idCamp;
r["campName"] = record.campName;
// Add the row to the table.
table.Rows.Add(r);
}
}
else
{
MessageBox.Show("Unhandled type. Add support for new data type in SmartTableViewer()");
return;
}
// Update table in grid
dg1.DataSource = table.DefaultView;
}
internal class tbCampView : tbCamp
{
}
}

Converting an entity model to a dataset - can this be done?

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;
}

Using LINQ, how do you get all label controls

I want to get a collection of all label controls that are part of a user control. I have the following code:
var labelControls = from Control ctl in this.Controls
where ctl.GetType() == typeof(Label)
select ctl;
but the result is zero results.
Please assist. Thanks.
Edit
I have also tried the following code without success.
this.Controls
.OfType<Label>()
.Where(ctl => ctl.ID.Contains("myPrefix"))
.ToList()
.ForEach(lbl => lbl.ForeColor = System.Drawing.Color.Black);
Again, without success.
Are you sure that the control whose child controls you are parsing actually directly contains Label controls? I suspect that it is a child of the main control that is hosting the labels, in which case, you need to recursively search through the UI tree to find the labels.
Something like:
public static IEnumerable<Label> DescendantLabels(this Control control)
{
return control.Controls.DescendantLabels();
}
public static IEnumerable<Label> DescendantLabels(this ControlCollection controls)
{
var childControls = controls.OfType<Label>();
foreach (Control control in controls)
{
childControls = childControls.Concat(control.DescendantLabels());
}
return childControls;
}
Controls.OfType<Label>() - thats all
For nested controls
public static class ext
{
public static List<Label> GetLabels(this Control control)
{
var chList = control.Controls.OfType<Label>().ToList();
chList.AddRange(((IEnumerable<Control>)control.Controls)
.SelectMany(c => c.GetLabels()));
return chList;
}
}
var labelControls = this.Controls.OfType<Label>();

Umbraco DataTypes. Retrieve list of possible data types.

I have a property in umbraco that uses a drop down data type with a set of prevalues that you can select from.
How do I retrieve a list of all the possible prevalues that are in this drop down list?
There's a helper method in umbraco.library that does that.
From xslt:
<xsl:variable name="prevalues" select="umbraco.library:GetPreValues(1234)" />
From code:
using umbraco;
XPathNodeIterator prevalues = library.GetPrevalues(1234);
Replace 1234 with the id of your datatype (You can see it in the bottom of your browser when hovering your mouse over the datatype in the developers section)
Regards
Jesper Hauge
Here is the code that I use in one of my Umbraco datatypes to get a DropDownList containing all possible prevalues:
var prevalues = PreValues.GetPreValues(dataTypeDefinitionId);
DropDownList ddl = new DropDownList();
if (prevalues.Count > 0)
{
for (int i = 0; i < prevalues.Count; i++)
{
var prevalue = (PreValue)prevalues[i];
if (!String.IsNullOrEmpty(prevalue.Value))
{
ddl.Items.Add(new ListItem(prevalue.Value, prevalue.DataTypeId.ToString()));
}
}
}
Replace dataTypeDefinitionId with the id of your datatype.
I know this is an old question, but I created this method based on the information provided in this answer and I think it is worth documenting:
public static class UmbracoExtensions
{
public static IEnumerable<string> GetDropDownDataTypeValues(int dataTypeId)
{
var dataTypeValues = umbraco.library.GetPreValues(dataTypeId);
var dataTypeValuesEnumerator = dataTypeValues.GetEnumerator();
while (dataTypeValues.MoveNext())
{
dynamic dataTypeItem = dataTypeValues.Current;
yield return dataTypeItem.Value;
}
}
}

Resources