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

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)
{
...
}

Related

Grails Transient as a lookup

Getting my feet wet with Grails, so please bear with me...
Just wondering if this is a good use of transient, or if there's a better way.
say I have
class Author {
String name
String favoriteBook
static transients = ["favoriteBook"]
etc.
"Favorite Book" is the title from the Book table of the a book published by the author. I have a database stored procedure (function) that I want to use to do this lookup. I don't want it persisted to the database, just evaluated on the fly when the Author list (and show) is executed. For the list, ideally it is sortable as well.
Note: using Oracle datbase
This obviously is not my real world example, I am actually working on extending a legacy database, and cannot touch that structure....I have a lot of stored procedures that can be utilized. So the question remains...I want my domain class to pull down a value from the database which is the result of a stored procedure.
I find examples on the web of using transients, but not in this way...am I misusing it? How do I utilize stored procedures within g&g and GORM?
I also find example of using stored procedures, like this one
http://www.craigburke.com/post/44771719252/oracle-stored-procs-in-grails
but missing how to implement this in the views...
tia...
K.
Instead of declaring it as a transient I would map it as a formula
class Author {
String name
String favoriteBook
static mapping = {
favoriteBook formula:'find_favorite_book(id)'
}
(or whatever the required SQL is to call your custom function).
Quoting from the linked documentation
Note that the formula expressed in the ORM DSL is SQL so references to other properties should relate to the persistence model not the object model.
i.e. if you need to refer to other properties in the formula then you have to use the database column names (some_property) rather than the property names (someProperty). If you don't want to have to guess the naming convention then you should consider making the property-to-column mapping explicit for any columns you want to use in the formula
static mapping = {
someProperty column:'my_unusual_column'
}

EAV - Get value using Linq to entities

In a data model like this (http://alanstorm.com/2009/img/magento-book/eav.png) I want to get the value from an EAV_Attribute using Linq to SQL.
Assuming that an EAV_Attribute only exists in one inherited table (varchar, decimal, int, etc.) how can I get it in a linq query?
I know that I can use the Inheritance for this, but I want to execute it in the SQL Database side...
Is it possible to do a kind of Coalesce in Linq, considering that the elements have different types?
EAV and linq is not a happy marriage. I think your best shot is to create an unmapped property in eav_attribute that resolves the value (as object) from it's typed attribute child. With entity framework, you won't be able to use this property in an expression (i.e. not in a Where or Select), You must convert to IEnumerable first to access it. (Linq-to-sql may allow it because it can switch to linq-to-objects below the hood).
Another option is to create a calculated column of type sql_variant that does the same, but now in t-sql code. But... EF does not suport sql_variant. You've got to use some trickery to read it.
That's the reading part.
For setting/modifying/deleting values I don't see any shortcuts. You just have to handle the objects as any object graph with parents and children. In sql server you can't use cascaded delete because it can only be defined for one foreign key. (This may tackle that, but I never tried).
So, not really good news, I'm afraid. Maybe good to know that in one project I also work with a database that has an inevitable EAV part. We do it with EF too, but it's not without friction.
First of all, I recommend using TPH and not TPT for EAV tables. (One table with multiple nullable value columns (one per type) + discriminator vs. one table per type.)
Either way, if you modelled the value entity as an abstract class (containing the two IDs) with an inheriting entity per value data type that adds the value property, then your LINQ should look like this:
var valueEntity = context.ProductAttributes.Where(pa =>
pa.ProductId == selectedProductId
&& pa.AttributeTypeId == selectedAttributeTypeId)
.SingleOrDefault() as ProductAttributeOfDouble;
if valueEntity != null
return valueEntity.Value;
return null;
Where the entity types are: Product, AttributeType, ProductAttribute, ProductAttributeOfDouble, ... ProductAttributeOfString.

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.

nhibernate table pr hierarchy fetching specific class with LINQ

I have a class hierarchy mapped into one table. There is one superclass and 8 different sub classes. A lot of my queries needs to fetch e.g. 2 of the sub classes only for a specific date.
The table has a discriminator column that nhibernate itself uses. But when using LINQ for querying it is not possible to use this discriminator as there is no property for it.
Is there a commonly used trick for only fetching specific sub class when using nhibernate ?
For now I first have Linq 4 Nhiberneate query that fetches all sub classes into a given period. And then uses Linq 4 objects to filter on the sub classes that I need.
Is it possible to expose the discriminator column of the table as a property and thereby be able to make a where clause on it ?
In Hql querying subclasses is done by class, so you'd do
from subclass
where subclass.DateTime = :myDateTime
The docs also say you can query hierarchies by the special class property, eg:
from Eg.Cat cat where cat.class = Eg.DomesticCat
I don't know if this is possible with the Criteria API or NH Linq Provider.
You could always get all the instances with the correct time, and then filter client side, eg:
var allCandidates = from super in session.Linq<SuperClass>()
where super.Date > DateTime.Now.AddDays(-1)
select super
var results = from candidate in allCandidates
where candidate.GetType() == typeof(SubClass)
select candidate
It's a bit nasty, and if the subset of classes you're querying is always the same, you might be better off inserting another class in the hierarchy and querying that.

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.

Resources