LINQ and Devexpress Grid Datasource - linq

I have a DevExpress grid (DevExpress.XtraGrid.GridControl 8.2) with a datasource set at runtime like so:
private DataContext db = new DataContext("connection string");
gridControl.DataSource = from t in db.sometable
select new
{
Field1 = t.Name,
Field2 = t.Email,
Field3 = t.City
};
This means that the view has no idea what the data is going to look like at design time. I like being able to set a LINQ query as the datasource, but I'd also like to specify what the view will look like at design time.
Is there a way that I can tell the view that it will be using this query?
Would the best solution be to create a small object for holding the
contents of what gets returned from
this query?

You will have to define a class for the return type of your LINQ query if you want the DevExpress grid to automatically pick up the columns for the data source. At design time, the WinForm binding engine is using reflection or ICustomTypeDescriptor if the source implements it to automatically discover the properties, their types, etc of the data source. The DevExpress grid is using this underlying binding mechanism and automatically generating the columns for you at design time based on the property information. In your case however, you're creating an anonymous type in your LINQ query which is not known or available at design time. Therefore, DevExress Grid cannot generate the columns automatically. As #Dennis mentioned, you can manually add columns to the grid in designer. You need to make sure that 'FieldName', I believe, on the column matches the property name on your data source.
If you go with a class, you may also want to implement INotifyPropertyChanged to make the grid aware of data changes in the data source.

IIRC, the xtragrid requires that the datasource implement a databinding interface (ie IBindingList(T)) for it to auto-generate columns and the items should implement INotifyPropertyChanged.
With that in mind: if you do create columns via the wizard at design time or in code at runtime, as long as you set the FieldName property of the columns, they will show the data from the datasource with a property of that name.
Notes:
I think it must be a property, auto or not, as I've found that it sometimes won't bind to public variables.
The property must be assigned something (default or otherwise).
There must be a parameterless constructor for the item.

The fields are known at design time (Field1, Field2, Field3).
According to DevExpress you can use IList, IListSource, ITypedList or IBindingList. The difference between them is whether you can add new rows or if changes are refin the control.
So you can use ToList():
private DataContext db = new DataContext("connection string");
gridControl.DataSource = (from t in db.sometable
select new
{
Field1 = t.Name,
Field2 = t.Email,
Field3 = t.City
}).ToList();
Note: I tested it using DevExpress 10.1, but if it does use the WinForms binding then it should still work according to MSDN.

I haven't worked with the DevExpress grid, but I've done a lot with the .NET DataGridView.
Does the DevExpress grid have the same functionality as the .NET DataGridView that auto generates columns?
If so, then it should display whatever fields are found in your query and will use Field1, Field2 and Field3 (from your example code) as column names.
Or just turn off the auto generate column feature and add the columns at design time. As long as they match what your query returns it should work fine.

Related

Visual Studio 2013 Dataset Designer refresh relations

I have an application with a dataset linked to an sql server database. I have updated some of the names or foreign keys and primary keys in the sql server. How do I make those changes translate to the data set. For example, I had a primary key called fk_temsempl_xxxxx. I changed it to fk_temsempl on the sql database. How do I get that change to show in the dataset designer in visual studio?
I have tried running custom tool by right clicking on the dataset and clicking run custom tool. That didnt work. I tried configuring the table adapter of one of the tables where a change occured, but the name of the relation didnt change.
You actually just right click the relation and choose Edit Relation... or double click on the line (when the mouse cursor changes from arrow to drag symbol) but I honestly wouldn't bother; you'll then have further refactoring to do in the code anywhere the relation is used, and it can be heavily used by visual designers.
You also get the problem that VS may not help you with the refactoring: in data binding scenarios most things that can be a source of data can also be a collection of multiple things that can be a valid DataSource. They then rely on a string DataMember to determine which of the collections of data in the data source should be used for the data.
For example, when a bindingsource is bound to list a DataTable, the bindingsource.DataSource property might be the DataSet object that contains the DataTable, and thebindingsource.DataMemberis a string of "YOUR_TABLE_NAME". the BindingSource might not be bound asmyBindignSource.DataSource = myDataSet.MyDataTable`. Refactoring inside strings involves a find and replace
DataRelations in a DataSet are created from foreign keys as they were discovered when the relevant table(s) were added to the dataset but it is important to note that, like DataTables and everything else, they are NOTHING to do with the database schema objects at all - they aren't permanently associated with them, the dataset entities are just set up looking something like the database objects when they (dataset entities) are first created. DataTables are created from only those columns selected, and whatever .NET datatypes closely resemble the types output by the query. For a table of:
Person
------
Name VARCHAR(50)
SSN INTEGER
Birthdate DATE
If you created the table with SELECT * FROM Person you'd get a datatable with Name (string), SSN (int), Birthdate (datetime) but if you made a new datatable in the dataset based on SELECT LEFT(Name, 1) as Initial, PADLEFT(SSN, 20) as PadSSN, DATEDIFF(day, Birthdate, NOW()) as AgeDays FROM Person then you'd get a datatable of Initial (string), PadSSN (string), AgeDays (int) - i.e. the datatable looks nothing like the db table. This concept of disconnection between dataset and db is pervasive, and really the only things that relate in any way to the database are the properties that specify which DB table/column a particular DataTable/DataColumn relates to for purposes of loading/saving data. Your Person.Name datacolumn can be renamed to Blahblah, but it will still have a .SourceColumn property that is set to "Name" - that's how the mapping between dataset and db works; dataset is predominantly completely independent of the db. Renaming a DB column would require a change to the SourceColumn property only
DataRelations don't even have this notion of linking to the parent relation in the database; there's no SourceRelation or SourceFK proeprty because there is no need to. They're set up with the same rules and a generated name all based on the rules of the FK, but then they function independently and only within the dataset. If you rename or even remove an FK from the db the dataset will carry on working in the same restricted way it always did; adding a datarow to a child table when no aprent row exists for it will throw an exception - none of it anything to do with the FK in the db, and the DataRelation can have different rules to the FK (e.g it can cascade deletes when the FK is NOACTION) or even different columns. You can have more or fewer DataRelations than the DB has FKs
Run Custom Tool is not a "contact the DB and see what changes have occurred there and replicate them into the dataset", it is a "turn the XSD that describes the dataset into a bunch of C# classes that implement strongly typed dataset/table/relation/column etc objects". Any time you change the XSD by making an edit in the visual designer and hit save, the custom tool is run. If you edit the XSD directly in a text editor you may need to run it manually to have your changes reflected in c# classes
Reconfiguring a tableadapter probably won't do anything to the relations either; its solely concerned with changing the datatable and tableadapter. If you really want to refresh the relations, delete the datatable from the set and recreate it. Be prepared for a potentially significant mop up/refactoring of code

LINQ update statement using generic table and column names

OK, I've seen a lot of posts on creating generic LINQ statements, but these are usually based on select queries. What I need is a LINQ UPDATE statement that takes a generic parameter for the table to update and a generic parameter for the column to update.
The data model I'm working with has dozens of tables, and each table has potentially dozens of columns. What I'm really driving toward is a single Update statement that allows me to tell it at runtime which table and which column to update.
Dealing with data typing of these dynamically supplied fields will also be an issue since obviously I can't update a DateTime column with a decimal value for example.
So, can anyone point me at some code that shows a LINQ update process using generic parameters for table and column names.
Any help would be greatly appreciated!
You didn't specify Entity Framework with DbContext but if that is what you are using, this is pretty easy. The following code is written to work within the NerdDinner sample which can be downloaded from http://nerddinner.codeplex.com/
This code locates a dinner based on the id and sets the address property to "New Value"
Dinner dinner = db.Set<Dinner>().Find(id);
var entry = db.Entry(dinner);
entry.Property("Address").CurrentValue = "New Value";
db.SaveChanges();

Using LINQ to compare a searchstring with the value of all the string properities of a EF class

In my ASP.NET application I have an EF Product class (derived from Product DB table) and I want to perform search functionality on its string fields by using inline LINQ.
Since I predict the name and amount of the fields (properties) will change I do not want to strongly couple my code with the table definition. How can I compare the values of all the fields in the table with a search string by iterating through all table fields (properties)?
I know one option is through reflection, is there any easier and more immediate way to fulfill this task?
In the end, your EF class is still just a normal .NET class. Unless EF explicitly provides some library for looping through properties (it doesn't that I know of), you'll still need to use reflection to do this.
var properties = typeof(Product).GetProperties(BindingFlags.Instance);
foreach (var property in properties)
{
...
}

How to create a reference to an existing record

go easy on me, it's my first question :)
I've been working with linqToSql for about a month, and there is just this one thing that is bothering me...
Lets say I have an Entity Object called "Customer" and another called "CustomerType", Customer as a reference to CustomerType.
When inserting the Customer I need to set the CustumerType, I have the customerTypeID value that I want to set, so what I am doing is this:
if(c.CustomerTypeReference == null)
{
c.CustomerTypeReference = new System.Data.Objects.DataClasses.EntityReference<CustomerType>
}
c.CustomerTypeReference.EntityKey = new System.Data.EntityKey("DataContext.CustomerType", "id", value);
This works but it seems to me over complicated. Is there any other way to do this?
Please take in mind that I do not want to get the object CustomerType from the database, this example is simple but I do work with objects that contain about 100 properties.
Are you using the DBML Designer or have you hand-coded your entity classes? If you are working with the Designer, I would expect that since your table has a customerTypeID column, that there would be a property named customerTypeID in your Customer class. All you really need to do is set the value of this property to the value of the id
Customer c = new Customer();
c.customerTypeID = value;
This should work fine as long as you don't want to refer to the related entities themselves (i.e., you are just going to save this particular object, not use it right away). If you need to refer to the related entities -- say to access their properties -- it's going to have to go retrieve the values from the database. I'd have to look at the designer-generated code, but I think that the property setters on the id-value columns don't update the entity references, while the entity-reference setters do update the id-value fields.

Linq to Entities, EntityReferences and DataGridViews

I am trying to select certain fields from my entity to be used as the datasource for a datagridview, but I haven't been able to make it work. Is such a thing possible? For example, I have a Customers entity that contains several entityreferences. I want to take fields from the customers entity and from within those entityreferences and display them in the datagridview. I haven't been able to come up with a Linq query to accomplish this, and even when you simply use the entire entity as the datasource the fields within the entityreferences are not displayed. Any idea what I am doing wrong? Thanks for the help.
from customer in context.customers
select new
{
Name = customer.Name,
City = customer.Address.City
}
that will create a custom object and you can see the second property is referencing an entity field on the primary entity.. basically just transform the data to a new object and bind the enumerable generated to the grid.
sorry if this is a little mumbled, typing on my phone.
Caveat: This is not tested with entity framework references.
When using object data sources you can reference properties of object references, but you must first cast the object:
<asp:Label ID="lblCity" runat="server" Text='<%# ((Customer)Container.DataItem).Address.City%>'></asp:Label>
Could this be your problem accessing properties of the entity references?

Resources