I am new to Linq. I have been using strongly typed data-sets but like the idea of Linq to create objects.
At the moment I use datasets to retrieve a table that joins data from tblProducts and tblProductSettings.
This is a one to many relationship as the products serve multiple websites with a unique tblSettings row for each website, however its assumed that there is always one row for tblSettings per website.
Example :
Select * from tblproducts, tblProductSettings where tblproducts.ProdID = tblProductSettings.ProdID and tblProductSettings.CreatorID = @CreatorID
The dataset will give a nice table to loop through and display the products with the settings.
Linq will give me a tblProducts object with tblProductSettings as a collection. I don’t want to have to loop a collection each time to get the settings as this will, i believe create a new sql query for each product and make accesses the settings a pain.
I can create a custom object tblProductsAll, but the only way I can fill this object is…
var Product = from p in context.tblProducts
join ps in context.tblProductSettings on p.ProdID equals ps.ProdID
where p.CreatorID == 1 && ps.ProdCreatorDisplay == 1
select new tblProductsAll()
{
ProdTitle = p.ProdTitle,
ProdPrice = ps.ProdPrice
};
I can then pass this model to the razor template.
My question is… is there a better way of setting the properties ? There are 20 or more different properties and i don’t want to have to keep setting them, repeating code, every time i want the same object somehwere in the site with a differnt where clause. Is there a way to stop this repetition ? i.e. automatically mapping the object, or reusing the select new statement.
Any help would be much appreciated.
When there are navigation properties, use them! Your
Productentity has a navigation propertyProductSettings. That means that the query could look like this:(Note that I stubbornly refuse to use the
tblprefix)But that does not tackle the repetitive code issue.
Enter AutoMapper. This is a nice little tool that removes boilerplate property copying statement from your code by defining and executing mappings between objects. The default mapping is based on name convention. E.g. the statement
Mapper.CreateMap<Product,ProductDto>();configures a mapping between all equally named properties ofProductandProductDto. AndMapper.Map<ProductDto>(product);would create aProductDtoobject fromproduct.But your
ProductsAllclass has a propertyProdPricethat comes fromProductSettings. How to deal with that?Here a nice feature of AutoMapper can be used. It also resolves properties of nested objects based on name convention. Suppose your class
Producthad a propertyTitle, AutoMapper can resolve that to a propertyProductTitlein the target object. Let’s use that:Project()is an extension method onIQueryable. The nice thing is that the SQL statement only contains the properties used in the projection. As you see, you can define a mapping once and for the rest use theProject().To()construct in your code.There’s much more to AutoMapper. This is a quick start.