I have an object Employee
public class Employee
{
public int Id {get;set;}
public ICollection<Address> addresses {get;set;}
}
public class Address
{
public int Id {get;set;}
public string AddressLine1 {get;set;}
public string City {get;set;}
}
Now the Employee is a part of my context.
How do I query the employee object where the address.city is "NY"? I want to traverse to the Address collection from the Employee object in the context.
Thanks
Try with this
MyDBContext.Employee.Where(e => e.Addresses.Any(a => a.city == "NY").ToList();
with this code you will get all Employees, for whom at least one of the address is in New york. If you want that all address of Employee be in New Yowk, then change Any for All.
Related
I am working on a risk monitoring application with a SQL DB in the background. I use EF 4 Database First. There is a "Position" class in the model, which models holdings in various types of assets. A position holds a reference to a "Contract" class. This "Contract" class serves as the base class for various types of financial contracts, such as "Investment".
The classes look as follows:
public class Position
{
public int ContractID {get;set;}
public DateTime PositionDate {get;set;}
public decimal MarketValue {get;set;}
}
public class Contract
{
public int ID {get;set;}
public string Description {get;set;}
public int CurrencyID {get;set;}
public Instrument Instruments {get;set;}
}
public class Investment:Contract
{
public int ID {get;set;}
public int BBGIndustryID {get;set;}
}
When i try to run a query and try to filter on properties from the "Investment" Class, the system throws an StackOverFlowException:
var dataPoint = _context.Positions.Where(c => c.Contract.Instruments != null).Where(c => c.Contract.Instruments.BBGIndustryID == 24).ToList();
How do i need to write the query that i can filter on properties from the derived classes, or do i need to move the properties i need to filter on to move to the base class?
I have a data model consisting of two entities
public class product
{
public int ID {get;set;}
public string Name {get;set;}
}
public class category
{
public int ID {get;set;}
public string Name {get;set;}
public IEnumerable<product> products {get;set;}
}
What I need to do: starting from category how can I sort by product name?
I've tried something like this:
api/categories?$orderby=?
If you query the Categories, you cannot order by Product name, simply because you can only order Categories by Category properties.
If you want to query the products of Category 1, for instance, you can search for api/categories(1)/products?$orderby=Name.
Given the following:
public class Department
{
public int DepartmentID { get; set; }
public string Name { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
public class Course
{
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
public int DepartmentID { get; set; }
public virtual Department Department { get; set; }
}
If I turn lazy loading off and issue the following:
var departments = _DepartmentRepository.GetAll()
.Include(c => c.courses);
Then I get the answers with a Department object inside of them.
Is there a way I can just include the courses and not get back the Department object. For example can I just include one level (courses).
You are just including one level. The department object inside the course is there because EF has done some relationship fixup so that you can navigate to the department from the course.
If you don't want departments then just get the courses directly. That is context.Courses.ToList(); or via a courses repo if you have one.
When fetching entities EF will automatically populate navigation properties where it is already tracking the target object. This means if you do say:
// Load the department with a PK of 1
_DepartmentRepository.Find(1);
and then, using the same context, for example:
// Load a course with PK of 17
_CourseRepository.Find(17);
If this courses department id is 1, then EF will have automatically populated it's Department navigation property even though you didn't specify the include. You could stop this behavior by not making the Department navigation property virtual.
My application has products and vendors and both of them have similar items in a "has a" relationship...in particular they have a "favorite" so users can bookmark them.
so we have:
public class Product
{
public int ProductId {get;set;}
public int Name {get;set;}
public List<Favorite> Favorites {get;set;}
}
public class Vendor
{
public int VendorId {get;set;}
public int Name {get;set;}
public List<Favorite> Favorites {get;set;}
}
public class Favorite
{
public int FavoriteId {get;set;}
public string UserName {get;set;}
}
At first this didn't work, so I added:
public int? VendorId {get;set;}
public int? ProductId {get;set;}
Now the issue I'm having is that my Vendor.Favorites and Product.Favorites are always null.
How do I bind these so that I can work with the objects like that? Do I not make it a separate entity?
Thanks!
UPDATE: I should note that I'm using MVC 3 Code-first with POCO.
UPDATE: Solution:
I don't think this is ideal, still working out the kinks with how I want this to work because It will add redundant code for adding favorites and reviews.
public class Product
{
public int ProductId {get;set;}
public int Name {get;set;}
public virtual List<Favorite> Favorites {get;set;}
}
public class Vendor
{
public int VendorId {get;set;}
public int Name {get;set;}
public virtual List<Favorite> Favorites {get;set;}
}
Having the raw nullable int variable in the favorites class makes it work, but if I wanted to use the favorites class with other objects I'll have to modify the favorites properties with a new mapping to the key of the object. Out of curiosity, when dealing with these classes normally, how do you manage the data storage for these objects? I'm assuming you deal with it at a DAL?
You could use inheritance, make a base class containing only Favorite then derive classes based on that for the other info. This establishes an "is a" relationship
Ex.
public class baseClass
{
public list<Favorite> Favorites { get; set;}
}
public class Product : base
{
public int ProductID { get; set; }
public string Name { get; set; }
}
Then a Product Object would have all 3 properties.
Based on the assumption that you're using EF 4.1:
Your model looks pretty good except I'd change
public int? VendorId {get;set;}
public int? ProductId {get;set;}
to
public virtual Vendor VendorId {get;set;}
public virtual Product ProductId {get;set;}
Then your FK relationships should be all set. By my understanding of EF, List<Favorite> is meant to establish a relationship and is not actually populated. You have to populate it yourself, either by calling .Include() on the context or by referencing the actual FK that EF creates in the database, which in your case would be VendorId_FavoriteId or ProductId_FavoriteId
I would keep one Property to store the ID's (either VendorID or ProductId) and use another property to tell me what type it is (Vendor or Product)
public class Favorite
{
public int FavoriteId {get;set;}
public string UserName {get;set;}
public int ItemID { set;get;} //can use a better generic name
public FavoriteType Type { set;get;}
}
I have an Enum for the Types
public enum FavoriteType
{
Vendor,
Product
}
And make sure you are initializing your sub properties before accessing them / applying a method on those so that It won't throw the null reference exception!. You can do it constructor itself
public class Product
{
public int ProductId {get;set;}
public int Name {get;set;}
public List<Favorite> Favorites {get;set;}
public Product()
{
if(Favourites==null)
Favorites=new List<Favorite>();
}
}
I am trying to separate a large table into multiple discrete types.
I'm following the example here: http://weblogs.asp.net/manavi/archive/2011/04/24/associations-in-ef-4-1-code-first-part-4-table-splitting.aspx?CommentPosted=true#commentmessage
It's working for a primary type and a sub-type, but does not work when I employ multiple types. I received an error
The Entity types 'CampaginFeedback' and 'CampaignSurvey' cannot share table 'Campaign' because they are not int he same type hierarchy
or do not have a valid one to one foreign key relationship with
matching primary keys between them.
Here are simplified versions of my classes:
public class Campaign {
[Key]
public int CampaignId {get;set;}
public string Name {get;set;}
public virtual CampaignSurvey Survey {get;set;}
public virtual CampaignFeedback Feedback {get;set;}
}
public class CampaignSurvey {
[Key]
public int CampaignId {get;set;}
public string Question {get;set;}
public string Answer {get;set;}
}
public class CampaignFeedback {
[Key]
public int CampaignId {get;set;}
public string Feedback {get;set;}
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Campaign>().HasRequired(c => c.Survey).WithRequiredPrincipal();
modelBuilder.Entity<Campaign>().HasRequired(c => c.Feedback).WithRequiredPrincipal();
modelBuilder.Entity<Campaign>().ToTable("Campaign");
modelBuilder.Entity<CampaignSurvey>().ToTable("Campaign");
modelBuilder.Entity<CampaignFeedback>().ToTable("Campaign");
}
Edit: Split table to more than two entities in code first is very problematic. It works without any problem when using EDMX.
To make it work you must ensure that each entity used to split table has valid one-to-one relation with all other entities used to split table. That also means spoiling your model with navigation properties and moreover ensuring that during save all navigation properties pointing to the same entity type reference the same instance (otherwise you will get exception during call to SaveChanges).
So the solution for your example should be something like:
public class Campaign {
[Key]
public int CampaignId {get;set;}
public string Name {get;set;}
public virtual CampaignSurvey Survey {get;set;}
public virtual CampaignFeedback Feedback {get;set;}
}
public class CampaignSurvey {
[Key]
public int CampaignId {get;set;}
public string Question {get;set;}
public string Answer {get;set;}
public virtual CampaignFeedback Feedback {get;set;}
}
public class CampaignFeedback {
[Key]
public int CampaignId {get;set;}
public string Feedback {get;set;}
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Campaign>().HasRequired(c => c.Survey).WithRequiredPrincipal();
modelBuilder.Entity<Campaign>().HasRequired(c => c.Feedback).WithRequiredPrincipal();
modelBuilder.Entity<CampaignSurvey>().HasRequired(c => c.Feedback).WithRequiredPrincipal();
modelBuilder.Entity<Campaign>().ToTable("Campaign");
modelBuilder.Entity<CampaignSurvey>().ToTable("Campaign");
modelBuilder.Entity<CampaignFeedback>().ToTable("Campaign");
}
I'm even not sure how this will work in the real scenario. You can find some other problems when using it.
Something I have found that works is to create a view and point your additional entities to that.