I have a "task" table, which has a "sub category". The sub category is related to a Category. A category has many sub categories, but my task item only stored the sub category id (The category can be deduced from this).
So, my entity framework seems to understand this relationship.
But, my link is failing.
public TaskObject GetTask(int taskId)
{
var item = (from t in _te.tasks.Include("r_sub_category").Include("r_category").Include("r_priority").Include("r_state").Include("assigned_person").Include("create_person").Include("update_person") where t.task_id == taskId select t).FirstOrDefault();
return Transformer.UnpackTask(item);
}
There is a r_category table, and entity object, but when I run this, it tells me:
A specified Include path is not valid. The EntityType 'taskerModel.task' does not declare a navigation property with the name 'r_category'.
And that's correct - r_category is linked to my r_sub_category table... and not directly to task. Is there a way to load the r_category?
Or, maybe this Include is lazy, and I should be doing some sort of Joining myself? Maybe more efficient?
You need to show the full path with dot Notation so im guessing it would be
"r_sub_category.r_category".
And so forth
Related
I am using this as a reference -- how concatenate multiple rows in LINQ with two tables?
I have the exact same needs, except that not all "printers" have "resolutions". In my particular case, I have a Lead table, which stores some basic information. Then there is a tag table, which stores tags used for the Lead. Not every lead has a tag.
This is what I have so far based on the above reference:
var leads = _dbRO.Leads.Join(_dbRO.Tags, p => p.LeadId, r => r.EntityId, (p, r) => new
{
LeadId = p.LeadId,
GigDate = p.GigDate,
Location = p.Location,
Tags = String.Join("|", _dbRO.Tags.Where(k => k.EntityId == p.LeadId)
.Select(lm => lm.TagName.ToString()))
}).Distinct();
This works well for me. However, leads without tags are NOT returned. How do I ensure all leads are returned regardless of tags. An empty string or null for Tags field would be fine.
Also if you don't mind, if I want to return the Tags in an object array, how do I do that? The reason is because there could be additional information associated with each tag, like color etc. So a simple concatenated string might not be sufficient.
Thanks a bunch!
I've figured out -- I do not need to join the tag table at all. This causes the problem. I just need to select from my Lead table and in the Select section, get the tags as I was already doing.
If you’ve declared a relationship between Lead and Tag entity types, then EF already supplies your requirements through the Include() extension method.
ctx.Leads.Include(l => l.Tags).ToList()
This requires that Lead declares a navigation property to Tag as shown below.
class Lead
{ ... public List<Tag> Tags { get; set; } }
I am way to customizing 'Sales' application that belongs to 'salesforce.com' platform.
Is there any way to select all the 'OpportunityProducts' objects which are belongs to particular 'Opportunity Id' ?
[SELECT Id FROM OpportunityProduct WHERE Opportunity =:opportunitId];
When I execute above code for select those 'OpportunityProduct', I got following error. If any one have some idea please update me. Thanks.
Save error: sObject type 'OpportunityProduct' is not supported. If you are attempting to use a custom object, be sure to append the '__c' after the entity name. Please reference your WSDL or the describe call for the appropriate names.
Another way to get this done when you need the actual products, not just the line items, is as follows. First get your opportunities:
List<Opportunity> opps = [SELECT Id, Name FROM Opportunity LIMIT 1000];
Then loop through to create a list of opportunity Ids
List<Id> oppIds = new List<Id>();
for(Opportunity o : opps)
{
oppIds.add(o.Id);
}
Now get your actual products that belong to your opportunities...
List<OpportunityLineItem> oppProds = [SELECT Id, PricebookEntry.Product2.Name, PricebookEntry.Product2.Family
FROM OpportunityLineItem
WHERE OpportunityId IN :oppIds];
Hope that helps.
how can I build a table of "orders" containing "IdOrder", "Description" and "User"?... the "User" field is a reference to the table "Users", which has "IdUser" and "Name". I'm using repositories.
I have this repository:
Repository<Orders> ordersRepo = new OrderRepo<Orders>(unitOfWork.Session);
to return all Orders to View, I just do:
return View(ordersRepo.All());
But this will result in something like:
IdOrder:1 -- Description: SomeTest -- User: UserProxy123ih12i3123ih12i3uh123
-
When the expected result was:
IdOrder:1 -- Description: SomeTest -- User: Thiago.
PS: I don't know why it returns this "UserProxy123ih12i3123ih12i3uh123". In Db there is a valid value.
The View:
It is showed in a foreach (var item in Model).
#item.Description
#item.User //--> If it is #item.User.Name doesn't work.
What I have to do to put the Name on this list? May I have to do a query using LINQ - NHibernate?
Tks.
What type of ORM are you using? You mention "repositories" but does that mean LinqToSql, Entity Framework, NHibernate, or other?
It looks like you are getting an error because the User field is not loaded as part of the original query. This is likely done to reduce the size of the result set by excluding the related fields from the original query for Orders.
There are a couple of options to work around this:
Set up the repository (or context, depending on the ORM) to include the User property in the result set.
Explicitly load the User property before you access it. Note that this would be an additional round-trip to the database and should not be done in a loop.
In cases where you know that you need the User information it would make sense to ensure that this data in returned from the original query. If you are using LinqToSql take a look at the DataLoadOptions type. You can use this type to specify which relationships you want to retrieve with the query:
var options = new DataLoadOptions();
options.LoadWith<Orders>(o => o.User);
DataContext context = ...;
context.LoadOptions = options;
var query = from o in context.Orders
select o;
There should be similar methods to achive the same thing whatever ORM you are using.
In NHibernate you can do the following:
using (ISession session = SessionFactory.OpenSession())
{
var orders = session.Get<Order>(someId);
NHibernateUtil.Initialize(orders.User);
}
This will result in only two database trips (regardless of the number of orders returned). More information on this can be found here.
In asp.net MVC the foreign key doesn't work the way you are using it. I believe you have to set the user to a variable like this:
User user = #item.User;
Or you have to load the reference sometimes. I don't know why this is but in my experience if I put this line before doing something with a foreign key it works
#item.UserReference.load();
Maybe when you access item.User.Name the session is already closed so NHib cannot load appropriate user from the DB.
You can create some model and initialize it with proper values at the controller. Also you can disable lazy loading for Orders.User in your mapping.
But maybe it is an other problem. What do you have when accessing "#item.User.Name" from your View?
Here is the expression
x => x.stf_Category.CategoryID == categoryId
x refers to an Product Entity that contains a Category. I am trying to load all Products that match given categoryId.
In the db the Product table contains a Foreign Key reference to Category (via CategoryId).
Question: I think I am doing it wrong. Is there something else one has to do in EF4 to create a LINQ expression of this type?
Are there any good examples of EF4 Linq expressions out there? Specifically something that queries on the basis of related entities such as my problem ?
Thanks !
You're looking for the Include method.
var query = db.Products.Include("Categories");
This is commonly referred to as eager loading.
Entity Framework will 'infer' the JOIN constraint based on the mapping you have specified.
The "magic string" needs to match the Entity Set name on your EDMX.
Check out this post for more info.
EDIT
I'm a little confused as to whether you want the Products and Categories, or just the Products which have a specific Category ID.
If the latter, this is the way to go:
var query = from p in db.products
join c in db.categories
on p.CategoryId equals c.CategoryId
where c.CategoryId == someCategoryId
select p;
Keep in mind though, the above query is exactly the same result as your original query.
If p is a product, then p.Categories will look at the Navigational Property of your Product entity on the EDMX, in which case it will be your Category FK.
As long as you setup your Navigational properties right, p.Categories is fine.
If you are using EF4 and the association between Category and Product classes has been picked up and defined in your Model, then all products with a specific categoryID can be selected as simple as:
x => x.CategoryID == categoryID
You don't need to join nor an eager loading for that.
I would like to populate a Treeview.
Here is what I have in DB :
table : Box
BoxID
BoxName
table Book :
BookID
BookName
BoxID (fk Box.BoxID)
table Chapter:
ChapterID
ChapterName
BookID (fk Book.BookID)
As you may know a treeview is made up of treenode object.
A treenode object have a text property and a tag property.
The "text" property is the text that it's display on the screen for this node and the "tag" is an "hidden" value (usually uses to identify a node)
So in my case; the fields ending with ID will be used in the "tag" property and the fields ending with Name will be used in the "text" property
example :
so for a book; I will use the BookID field for the "tag" property and BookName field for the "text" property
note : I use a dbml so I have a Book object, Box object and Chapter object and I use linq to get them from the db.
So my question is; what is the best practice to build this tree?
I have a solution but it's really ugly because it looks like I'm duplicating the code.
The problem is that the values I need to extract for the text and tag properties are identified by differents fields name in the db
So for the book level, I need to get the BookID field to populate the tag property of my node; for the box level, I need to get the BoxID field to populate the tag property , ....
How can I make a kind of generic way to do it ?
I hope I made myself clear enough, don't hesitate to ask me questions :)
Thx in advance
Here is what I have for the moment
I get the list of box with a linq (dbml) request.
List<Box> MyListofBox = getMyListofBox();
Treenode tnBox = null;
Treenode tnBook =null;
foreach(Box b in MyListofBox )
{
tnBox = new TreeNode();
tnBox.tag = b.BoxID;
tnBox.text = b.BoxName;
List<Book> MyListofBook = getMyListofBookByBoxID(b.BoxID)
foreach(Book boo in MyListofBook )
{
tnBook = new TreeNode();
tnBook.tag = boo.BookID;
tnBook.text = boo.BookName;
tnBox.nodes.add(tnBook);
}
mytreeview.nodes.add(tnBox);
}
but of course I don't like this solution...
do you have a better way ?
I would extract the you need from the database in the form of a struct, possibly via the anonnoumous type that has been added to C# together with linq. Then I would populate insert this data into the place in the tree.
From what I get, you are trying to get each property separately, which will not work so well, because then you will have to make a call to the database for each separate property, which is very wasteful.
Addition based on what you have added
I do not believe the code can be more compact - the names you call are similar, but not the same and the way you do it was what I was trying to explain earlier.
You could
Define an key/value interface that both Box and Book implement
Define a delegate that returns a TreeNode and create delegate methods that accept Box and Book
However, I think the code is fine as written. Sometimes you just have to code it and there's little point in further abstracting or optimizing it.
The only issue I see in the code is that you're making a database call in a loop. Whether or not that's a problem depends on the application.