WebAPI and OData OrderBy - asp.net-web-api

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.

Related

Query inner collection using Entity Framework

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.

Linq to Entities: How can i filter in the where clause on fields from a derived type (Table per Type inheritance)?

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?

asp.NET MVC 3 Composite pattern model binding

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>();
}
}

What is the standard pattern to retrieve JOINed data from normalized tables?

I have the following simple "textbook" classes defined:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
The Category field in Product is an integer referencing the Id field in the Category class. In the database, it would be a foreign key relationship between the Product and Category tables.
But my application would need to show the friendly name of the Category of a product.
Q1: Is it correct practice to define a new class as follows:
public class ProductJ : Product
{
public string CategoryName { get; set; }
}
And then, if I now have a method getProductsJ as follows:
public class Test
{
public List<Category> Categories = new List<Category>() { ... };
public List<Product> Products = new List<Product>() { ... };
public List<ProductJ> getProductsJ()
{
var products = from p in Products
join c in Categories on p.Category equals c.Id
select new ProductJ { Id = p.Id, , Name = p.Name, CategoryName = c.Name }; //!
return products.ToList();
}
}
Q2: Is the above the best way to retrieve a list of Products with Category names?
Q3: In the select statement (//!) is there a faster way to populate the fields of the base class Product linqwithout having to enter them one by one?
Thanks.
You could project the result of the join into an object that contains a reference to both the product and category.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public int Category { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ProductCategory
{
public Product Product { get; set; }
public Category Category { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<Category> Categories = new List<Category>();
List<Product> Products = new List<Product>();
var products = from p in Products
join c in Categories on p.Category equals c.Id
select new ProductCategory { Product = p, Category = c };
var list = products.ToList();
}
}
Does each book belongs to one category, or can it belong to more than one category in your case? because if a book belongs to one category then you can simply move the category name in the Book Table. also i will suggest to have a look on
MVC LINQ to SQL Table Join Record Display

How do I use Linq and Entity Framework to join two jointables?

I have a very normalized database, and I'm trying to join two join tables together.
My goal is to only show documents that the user has permission to. I'm using Entity Framework, and have several foreign keys set up for the following tables:
Relationships (Foreign Keys)
Users ---------------------------------------------
|
UserGroupMembership (UserID, GroupID)
|
|
Groups ----- -------------------------------------------------|
|
|
|---------------------------------------------------------|
|
|
XDocuments XDocumentSecurity (DocumentID, GroupID)
| |
---------------------------------------------
Table Definition
public partial class Users : EntityObject
{
public int UserID {get;set;} //PK
public string UserDisplayName {get;set;}
public DateTime CreateDate {get;set;}
public DateTime LoginDate {get;set;}
}
public partial class Groups : EntityObject
{
public int GroupID {get;set;} //PK
public string GroupDisplayName {get;set;}
public DateTime CreateDate {get;set;}
public DateTime LoginDate {get;set;}
}
public partial class UserGroupMembership: EntityObject // JoinTable
{
public int UserID {get;set;} //PK
public int GroupID {get;set;} //PK
// Not sure if this extra columns below causes an issue
public bool CanView {get;set;}
public bool CanDelete {get;set;}
public bool CanUpdate {get;set;}
public DateTime CreateDate {get;set;}
}
public partial class XDocumentSecurity : EntityObject // JoinTable
{
public int DocumentID {get;set;} //FK
public int GroupID {get;set;} //FK
public DateTime CreateDate {get;set;} // Not sure if this extra column causes an issue
}
public partial class XDocuments : EntityObject
{
public int DocumentID {get;set;} //PK
public string URL {get;set;}
public DateTime CreateDate {get;set;}
}
I've heard of many stories about how Linq to EF alters the SQL query in a way that is sub-optimal for performance.
Here is is the .Union operator sample that seems most applicable to what I'm doing. I could simply get a list of groups the current user is a member of and issue a modified version of this query:
public void Linq50()
{
int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };
int[] numbersB = { 1, 3, 5, 7, 8 };
var commonNumbers = numbersA.Intersect(numbersB);
Console.WriteLine("Common numbers shared by both arrays:");
foreach (var n in commonNumbers)
{
Console.WriteLine(n);
}
}
Question
How do I view the SQL query that EF generates?
What is a better way to approach this problem (if any)
You can also view the SQL generated by EF 4.1 using either
SQL Profiler
LINQPad
Although, at this time, you need to use the LINQPad beta for EF 4.1.
Regarding your second question, I believe your query would translate fine. Using LINQPad to check the SQL, the following query
var a1 = Addresses.Where(a => a.City.ToUpper().EndsWith("L")).Select(a => a.AddressID);
var a2 = Addresses.Where(a => a.City.ToUpper().StartsWith("B")).Select(a => a.AddressID);
var x1 = a1.Intersect(a2);
translates to
SELECT
[Intersect1].[AddressID] AS [C1]
FROM (SELECT
[Extent1].[AddressID] AS [AddressID]
FROM [Person].[Address] AS [Extent1]
WHERE UPPER([Extent1].[City]) LIKE N'%L'
INTERSECT
SELECT
[Extent2].[AddressID] AS [AddressID]
FROM [Person].[Address] AS [Extent2]
WHERE UPPER([Extent2].[City]) LIKE N'B%') AS [Intersect1]
I think #Slauma's recommendation to use navigation proeprties is the way to go if your model supports it.
Still, get LINQPad - you won't regret it :)
If you have navigation properties for all your keys and foreign keys an alternative query without an Intersect would be:
var query = context.XDocuments
.Where(d => d.Groups.Any(g => g.Users.Any(u => u.UserID == givenUserId)));
("Filter all documents which are in at least one group which has at least one user with the key = givenUserId")
I don't know if this will be better with respect to performance.
In EF 4.1 you can inspect the generated SQL simply by:
var sql = query.ToString();
Edit
My understanding how your model would look is the following:
Three entities with corresponding tables:
public class User
{
public int UserID { get; set; }
public ICollection<Group> Groups { get; set; }
}
public class Group
{
public int GroupID { get; set; }
public ICollection<User> Users { get; set; }
public ICollection<XDocument> Documents { get; set; }
}
public class XDocument
{
public int DocumentID { get; set; }
public ICollection<Group> Groups { get; set; }
}
And between User and Group a many-to-many relationship and between Group and XDocument as well:
modelBuilder.Entity<User>()
.HasMany(u => u.Groups)
.WithMany(g => g.Users)
.Map(c =>
{
c.MapLeftKey("UserID");
c.MapRightKey("GroupID");
c.ToTable("UserGroupMembership"); // join table name, no entity
});
modelBuilder.Entity<XDocument>()
.HasMany(d => d.Groups)
.WithMany(g => g.Documents)
.Map(c =>
{
c.MapLeftKey("DocumentID");
c.MapRightKey("GroupID");
c.ToTable("XDocumentSecurity"); // join table name, no entity
});
In this model and mapping the query described above should be possible. There is no need to access the join tables directly (and you can't actually access them via LINQ to Entities, EF manages those tables internally).

Resources