How do I query navigation properites using linq to sql and ef - asp.net

I am trying to strongly type a query for 3 ef objects using linq to sql. There are one-to-many relationships with product and category. My classes contain navigation properties and look like this.
public partial class Product
{
public int ID {get;set;}
public string Name {get;set;}
public virtual ICollection<Group> NpGroup {get;set;}
}
public partial class Category
{
public int ID {get;set;}
public string Name {get;set;}
public virtual ICollection<Group> NpGroup {get;set;}
}
public partial class Group
{
public int ID {get;set;}
public int ProductID {get;set;}
public int CategoryID {get;set;}
public virtual Product NpProduct {get;set;}
public virtual Category NpCategory {get;set;}
}
Trying to avoid the string based .Include(), how would I construct a query that returned a group equal to ProductID "1" but also included the names of the product and category?
Something like:
var context = ObjectContext.CurrentObjectContext;
var query = from c in context.Group
where c.ProductID == 1
//Include the names of the product and category of the group record (c.NpProduct.Name etc.)
select c;
I am probably missing the trees through the forest but I can not seem to get the syntax of ObjectContext.LoadProperty (if that is the right way to go).
Any thoughts? Thanks.

First of all, i doubt you are using both L2SQL and EF, so try not to confuse people.
Anyways, with EF - there is two ways to load the navigational properties:
1 - Eager Loading
q.Include("NavPropertyName")
2 - Explicit Load
*After* running your above query - use q.NavPropertyName.Load()
Difference is option 2) causes 2 queries, option 1 causes an inner join on the FK.
I can sympathise with your reluctance to use Include because of the 'magic strings' - i'm not sure why the EF team didn't make them strongly typed, however im sure there was a good reason.
More info on Load/Include here.
HTH

I think we all hate to use the typed string in the .include() statement.
I've started to use a enum to represent the table name, just to avoid spelling errors, etc.
for my database of about 70 tables it took me 10 min. to create the enum and my linq is now something like this:
var context = ObjectContext.CurrentObjectContext;
var query = from c in context.Group.Include(TableEnum.Category.ToString())
where c.ProductID == 1
select c;
Again, not perfect, but at least it's checked by the compiler

Related

ServiceStack ORMLite - Select columns

I recently started working with ServiceStack and its ORMLite framework. I have searched on Google and browsed the source code but couldn't find anything relevent.
Is there any way to select specific columns when executing a query with ORMLite ?
Something like that : Db.First<Model>(q => q.Id == someId, "Column1, Column2")
Unless I missed this feature, I am surprised nobody asked about this before, since this is one the rule of thumbs to optimize your DB transactions.
If you want to specify columns other that the table you need to use SQL as seen in this earlier example
So in your case you could do something like:
Db.First<Model>("SELECT Column1, Column2 FROM AnyTableOrView");
You can also create a partial model that looks at your table by decorating it with the [Alias] attribute, like:
[Alias("AnyTableOrView")]
public class Model {
public int Id { get; set; }
public string Column1 { get; set; }
public string Column2 { get; set; }
}
Then you can do something like:
Db.First<Model>(q => q.Id == someId);
And it will only SELECT + populate fields from the partial model.
I did try this :
Created a Database VIEW (table name and columns are already set)
Created a class named "Event" and matching each fields for that table with a property
(i used [Alias] for table name and for all columns to have nice names)
Wrote access to DB to select 1 record based on it's ID
var dbFactory = new OrmLiteConnectionFactory(
"Data Source=MyDB;User Id=user;Password=pwd", // Connection String
OracleDialect.Provider);
using (var db = dbFactory.OpenDbConnection())
{
var event = db.GetByIdOrDefault<Event>( request.Id );
}
At that point the var 'event' is populated but only the Id field is filled !
all the others fields of the class are not filled (while there are really data in database).
It's the simplest i can do and it does not work. Any ideas ?
(PS : i am using OrmLite for Oracle)
Thanks
I have found the problem.
It was due to an incorrect type matching between field in my class (defined as a string) and the corresponding Oracle Field (that is a DATE).
I replaced the string with datetime and worked like a charm.
So it's working perfectly with a VIEW and that's GREATLY simplify the code.
I had a similar problem, however my solution was different.
I had a int property in my POCO. My query (from Oracle) was returning a null for this property. It caused a exception to be raised and prevented further processing of that row.
The result was a partial populated POCO.
The solution was to change to type to be nullable.
public int? mypropperty

Mapping of "complex" ViewModels

I'm assuming this is a very very simple question. I'm wondering if I'm making a huge mistake because I supposed that this would be obvious but It's not working.
I'm trying to show a view which is using a viewmodel created specifically. Let's assume we are talking about:
public Order ActualOrder {get;set;}
public OtherType OtherVariable {get;set;}
public OtherType OtherVariable {get;set;}
Order is a complex type which holds some fields like:
[Required]
public int OrderId {get;set;}
[Required]
public string ClientName {get;set;}
[Required]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}")]
public DateTime DateAndTime {get;set}
I'm mapping in the view as:
#Html.EditorFor(p => p.Order.OrderId)
#Html.EditorFor(p => p.Order.ClientName)
#Html.EditorFor(p => p.Order.DateTime)
Everything works perfect in this line of communication. However, when I try to read the viewModel at the Action the variables are not set and, for example, the DateTimes are set to 01/01/0001 (which is wrong) but the client name is correctly set.
Viewmodel and Order have default constructor. Also, If I see the HTML generated the 'name' attribute seems to be correctly set.
I can't see the interactions that can be harming the mapping.
IMPORTANT
I've noticed that the problem comes from a jQuery DataPicker component. However, I'm using Firebug and I don't see 'name' or 'id' changing. Why the framework is not able to bind the model?

Best Practices for MVC.. ViewModel Binding using Interfaces Example

I am new to ASP.NET MVC 3.0 and trying to build an application using the MVC ViewModel design..
I was wondering what the best practices are regrading controllers for ViewModels and have a few questions below.. This is my understanding so far (which might be wrong)..
We create Models.
Create ViewModels by making a new class and declairing attributes with the same name and type as the base model classes (including ID fields of the base models you want to update later.. and the classes are not linked in any way).
Create a Repository for each of the base models (to find and save data ect.).
Create a Controller action for each of the ViewModels (which access the repositories of the base classes to retrieve values and put these values into the ViewModel, then pass the ViewModel to the ViewModels View).
Create Views from the ViewModels (ViewModel Views)
In the ViewModel controller Update (POST) method recieve the updated ViewModel object and convert it into base model objects (Maybe use Automapper?) and next save the base model objects back using their repositories and apply binding like this? "TryUpdate<'IPerson>(person)", "TryUpdate<'IPlace>(place);" (this looks wrong, the aim is to put the values back into the base classes from the ViewModel, apply binding, save base models back using the repositories!.. This doesnt appear to use the repositories.. Instead of TryUpdate<'IPerson>(person); I would expect to see something like this: person.Save(IPerson).. where "person contains the values", ".Save is the repository", and "IPerson contains the binding attributes to use for binding"?.. Not sure if this is right..
So far I have created ViewModels by making a new class and adding attributes from different base models using the same names. At this point i have the following questions:
Q1: Does each ViewModel have its own controller and access each of the base models repository classes to get its values?
Q2: in the ViewModel should you include the ID field of all of the base models that you are using attributes from, considering that you might want to POST an Update back through the ViewModels Controller to the base Models repository (needing the ID values)?
Q3: How would you bind attributes using an interface for binding the model in the controller using the repository to save.
I have been unable to find a tutorial or resource that explains everything in a step by step example, A complete answer would be the following example:
2x simple models, 1x simple viewModel, 1x interface for binding, 1x simple controller using an interface class for binding on update, 1x repository.. i.e.
//Model1
public class Person
{
int PersonID {get;set;}
string FirstName {get;set;}
string LastName {get;set;}
DateTime DOB {get;set}
}
//Model2
public class Place
{
int PlaceID {get;set;}
string Description {get;set;}
string AreaType {get;set;}
string PostCode {get;set;}
}
//ViewModel (containing attributes from models)
publc class ViewModel
{
//Person attributes
int PersonID {get;set;}
string FirstName {get;set;}
string LastName {get;set;}
//Place attributes
int PlaceID {get;set;}
string Description {get;set;}
string AreaType {get;set;}
//other attributes
string someOtherAttributeForDisplay {get;set}
}
//Model1 interface (for binding on model)
public interface IPerson
{
string FirstName {get;set;}
}
//Model2 interface (for binding on model)
public interface IPlace
{
string Description {get;set;}
string AreaType {get;set}
}
//ViewModelController?
{
//What goes here?
}
//Repository?
{
//what goes here?
}
I think you may have overcomplicated a very simple concept.
First off some general rules:
Don't use TryUpdateModel. Just don't.
For the same reasons, don't use any "auto" mapping mappers to map from your view model to your entities. Auto mapping the other way round (from entity to view model) is fine.
Your use of interfaces is unnecessary.
View models are supposed to be very simple classes that contain just the information you need for your view. If your view POSTs different information from what it displays, then just create a different view model for POST.
We use a naming convention of {Controller}{Action}Model for our view models. So for an action named "List" on a "Post" controller we will have a model called "PostListModel".
Finally, check out my response here Real example of TryUpdateModel, ASP .NET MVC 3

Nhibernate Criterion - select rows in table A of TypeId defined in Table B

the title is confusing sorry, if you can think of a better one, please change it.
I have three tables, say, bikes, owners and a relationship table (something like many to many) that defines all owners of a bike, or all bikes of an owner.
So, I want to select All bikes of OwnerId 1
But, my mapping is like so:
BikeOwners references one Bike
BikeOwners References one OWner
How do I write the criterion in nhibernate to do this?
Right now, I am trying:
DetachedCriteria crit = DetachedCriteria.For<Bikes>()
.Add(Expression.Eq("OwnerId", _ownerId));
and it errors out saying there isn't any OwnerId in Bikes table, which I understand..
Hope the question is clear.. If you need any details, please ask!
I know I can get first get a list of all Bike id's from Bike owner table and then use that int array to get all bikes in bikes table - BUT - it is two database access and I am doing it manually, there should be a way to do this in one go, right?
This is my plan b, if all else fails, I'll do this.
Thanks
It really depends on your entities. I have mocked up a sample entity, just adopt it to yours.
public class Bike
{
public int BikeId;
public IList<BikeOwners> BikeOwners;
public string BikeName;
}
public class Owners
{
public int OwnerId;
public IList<BikeOwners> OwnersBikes;
public string OwnerName;
}
public class BikeOwners
{
public int Id;
public Owners owner;
public Bikes bike;
}
Now, you are going to write your nhibernate criteria like this:
DetachedCriteria crit = DetachedCriteria.For<Bikes>()
.CreateCriteria("BikeOwners") //from Bikes class
.CreateCriteria("owner") // from BikeOwners class
.Add(Expression.Eq("OwnerId", _OwnerId)); //from Owners class
obviously, you need to modify it to your entities and names.
Unless there's more column in the BikeOwners table, it shouldn't be represented in the domain model at all. Bike and Owner should be mapped as a many-to-many relationship. Also, I find it unusual that a Bike can have multiple Owners.

21 entities with the same structure. What I'm supposed to do when it's time to make a CRUD for these entities

I Have 21 entities with the same structure.
Same Attribute too.
Every entity contains these Attributes :
AreaType
ID
IsActive
LangID
TXT
ModuleType
ID
IsActive
LangID
TXT
...
What I Need to perform a generic Crud. I already know that I need to create a generic repository. My problem is to perform a kind of generic ViewModel.
How can I create a generic View for the Create Form.
I Dont know what I need to pass in the Inherits of the view to be Generic.
... Inherits="System.Web.Mvc.ViewPage<...Dont know>"
Any Idea ?
A common approach this problem is to use ViewModels. This is where you create specific classes to be used as the models in your strongly typed views. These classes would not be the ones created by EF. The ViewModel classes can have a common base that encapulate your common fields. In your data access layer you would need to move data between your ViewModel classes and your EF classes. Things like AutoMapper (from CodePlex) work really well to reduce, if not eliminate, all of the the tedious "left-hand right-hand" coding.
Not too familiar with MVC, but (assuming it fits in with your hierarchy), I think you could create an abstract class which contains the properties you need, e.g.
public abstract class ViewableObject {
public abstract int ID {get; set;}
public abstract bool IsActive {get; set;}
// etc
}
Then implement that with your normal classes (AreaType and so on), e.g:
public class AreaType: ViewableObject{
public override int ID { get; set; }
public override bool IsActive{ get; set; }
}
and make the view use the abstract class.
... Inherits="System.Web.Mvc.ViewPage<ViewableObject>"
One idea is to simply change your underlying tables. Combine AreaType and ModuleType into a single "WhateverType" table that contains a field identifying exactly what type it is. Then when you codegen your classes you'll have exactly one class to deal with.
However, there are other concerns and you should only do this if it makes sense in your application.

Resources