Linq to Entities, EntityReferences and DataGridViews - linq

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?

Related

linq to sql, how to define DataContext without specifying Table properties

My intent is to create a generic (not in C# meaning) database model for Windows Phone using linq to sql. User of such model should be able to pass an array of his data object types (classes marked with Table attribute) to model's contstructor, and then model should take care about adding related tables to database and provide API for CRUD operations.
But then I've found out that in order to add tables to database, your data context (class inherited from DataContext class) have to declare each table as a property! That's embarrassing. Does this fact mean that my idea is not implementable? Because I obviously cannot add properties to my DataContext-based in the runtime.
So my question is, am I right in my judgments? If yes, are there some workarounds to solve this issue?
Thanks in advance.
EDIT: better question tagging, for somebody finally notice this.
You do not need to use a strongly typed DataContext (a class inheriting from DataContext and declaring properties for each table). You can do something like the following instead
var context = new DataContext("connection string", new AttributeMappingSource());
var table = context.GetTable<T>();
where T is some type marked with the Table attribute.

Partial loading of Entity Framework entities and passing them to presentation layer

If I want to select only few columns when retrieving data for an EF entity and cast them to the Entity type, I am not able to do that because it throws an error as mentioned in this post
The entity cannot be constructed in a LINQ to Entities query. I don't want to select all the columns, because I need only few of them. I can use anonymous types, but if I am using repository pattern and want to encapsulate all data access code in repository object and pass strongly typed object collection to the controller (not an anonymous object collection), how can I achieve that? Is the only option to define a DTO object for every subset of the properties for the EF entity? I know there is a risk of losing data with partial loaded entities, but if I am ready to take the risk and want full control over data updates, is that not possible?
for example I would like the "ProductRepository" method signature to be like this
public IEnumerable<Product> GetProducts(int categoryID) //selection of subset of data
and I want to pass this product collection from the controller to the view (in ASP.NET MVC project) and in the view I want to have strongly typed model (with intellisense) object. Is this possible? if not, I may have to reconsider using EF for my project due to this limitation. I am using EF 4.1 version.
Yes the option in this case is special object for each subset of properties you want to select. You can call the object DTO because it is just a result of the projection. This is the correct approach because if your UI doesn't need other properties of entity type it is correct to pass it only specialized ViewModel.
Another more complex (and worse) option is selecting anonymous type inside your Linq-to-entities query, calling ToList and after that construction the real entity type. Partial entity selection is not allowed and projecting to mapped entity types is not allowed as well. That is the reason why you have to use such a cumbersome approach. Example:
// Select anonymous projection
var query = from x in context.Entities
where ...
select new { ... };
// Repopulate entity type
var reultSet = query.ToList().Select(x => new Entity { ... });
Yes, what you want is totally possible using viewmodels instead of entities. Here is example controller code:
var productEntities = productRepos.GetProducts(6);
var productViewModels = Automapper.Mapper
.Map<IEnumerable<ProductViewModel>>(productEntities);
return View(productViewModels);
Your view model will have only the properties it needs for the view. Check out automapper.

LINQ and Devexpress Grid Datasource

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.

How to programmatically hide a linq-to-sql column on a datagridview?

I'm binding a linq Query to a datagridview for the purposes of allowing a user to insert/update/delete. However I'd like to hide the Id column. but I'd rather not hard code the
datagridview.columns[id].visible=false
In the event the id column name changes. I've read that you can walk through reflection to get a run-time list of columns, but I can't have that checked at design-time for a column name. Is it possible?
If I change the query to not include the ID, then I'm hard coding the column list instead of the id column name, so if columns were added, I'd have to go manually update there instead.
If you're using Winforms, then you should have a BindingSource on your Form that is typed to your LINQ-to-SQL type. If you do this, then you'll get full designer support for all of the fields available on that class.
If you're doing a lot of data binding work with LINQ-to-SQL entities (or any other classes, for that matter), I highly recommend checking into HyperDescriptor by Mark Gravell. It speeds up the UI data binding performance considerably by bypassing repeated runtime invocations of the properties on the classes.
Couldn't you do it in the html? Or are you using ASP.NET?
<asp:BoundField DataField="id" Visible="false" />

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.

Resources