Complex LINQ or EF query - linq

I have the following 3 classes.
A workflow configuration has one brand and one workflowtype.
I need one method in linq or EF that gets me all the brands of existing workflowconfiguration and another method that gets me all the brands of non existing workflow configuration.
I am lost cause I dont know where to start.
public class Brand
{
public int BrandId { get; set; }
public string Name { get; set; }
}
public class WorkflowType
{
public int WorkflowTypeId { get; set; }
public string Name { get; set; }
}
public class WorkflowConfiguration
{
public int WorkflowConfigurationId { get; set; }
public WorkflowType WorkflowType { get; set; }
public Brand Brand { get; set; }
public virtual ICollection<Approver> Approvers { get; set; }
}
Update1
Here are how my tables would look like and the expected result
Brand
Audi
Volkswagen
Mercedes
WorkflowTYpes
type 1
type 2
type 3
WorkflowConfiguration
brandid, workflowtype id
1 ------------ 1
1 -------------2
List<string> GetBrandsForExistingWorkflowType(string worfklowtype)
If I pass type1 to this method it should return:
Audi because for type1, audi exists on the table
List<string> GetBrandsForNonExistingWorkflowType(string workflowType)
If I pass type1 to this method it should return.
Volkswagen and Mercedes because for type1, those 2 brands are not in the relationship.

I think this is what you want:
List<string> GetBrandsForExistingWorkflowType(string worfklowtype)
{
var result = db.WorkflowConfigurations
.Where(x => x.WorkflowType.Name == worfklowtype)
.Select(x => x.Brand);
return result;
}
List<string> GetBrandsForNonExistingWorkflowType(string workflowType)
{
var excluded = GetBrandsForExistingWorkflowType(string worfklowtype);
var result = db.Brands.Except(excluded);
return result;
}

Related

EF Core non-existant column in query, how to rectify?

working my way through an EF core project I have inherited and am quite new when it comes to LINQ/EF core.
I'll cut this back to simplify things, and will demonstrate my problem with 4 basic tables.
Customer
CustomerId
Name
Contact
1
John
john#gmail.com
2
Peter
peter#gmail.com
CustomerTrade
Id
CustomerId
OtherDetail
T1
1
xyz
T2
1
abc
CustomerTradeParameter
ParamID
TradeId
Value
X
1
1234
Y
1
5678
CustomerTradeParameterType
ParamID
Name
OtherGenericInfo
X
Hello
Null
Y
Test
Null
Models
public class Customer : AuditableEntity
{
public long CustomerId { get; private set; }
public string Name { get; private set; }
public string Contact { get; private set; }
public virtual ICollection<CustomerTrade> CustomerTradeList{ get; set; }
protected Customer()
{ }
public class CustomerTrade : AuditableEntity
{
public long Id { get; private set; }
public long CustomerId { get; private set; }
public string OtherDetail { get; private set; }
public virtual ICollection<CustomerTradeParameter> CustomerTradeParameterList { get; set; } = new List<CustomerTradeParameter>();
protected CustomerTrade() // For EF Core
{ }
public class CustomerTradeParameter : AuditableEntity
{
public long TradeId { get; set; }
public string ParameterType { get; private set; }
public string Value{ get; private set; }
protected CustomerTradeParameter() // For EF Core
{ }
}
DTOs
public class CustomerTradeDto : AuditableDto
{
public long Id { get; set; }
public long CustomerId { get; set; }
public virtual ICollection<CustomerTradeParameterDto> CustomerTradeParameterList { get; set; } = new List<CustomerTradeParameterDto>();
}
public class CustomerTradeParameterDto : AuditableDto
{
public long TradeId { get; set; }
public string ParameterType { get; set; }
public string Value { get; set; }
}
The below query is attempting to retrieve a specific trade, and a list of its relevant parameters.
IQueryable<CustomerTradeDto> foundTrade = _database.CustomerTrade
.Select(trade => new CustomerTradeDto
{
Id = trade.Id,
CustomerId = trade.CustomerId,
CustomerTradeParameterList = trade.CustomerTradeParameterList.Select(param => new CustomerTradeParameterDto{
ParameterType = param.ParameterType,
TradeId = customerTrade.Id,
Value = param.Value
// (second question written further below) - If I wanted to additionally retrieve the CustomerTradeParameterType record
// (to get the name of this parameter), how would I embed this join?
// I originally had ParameterType defined as a "CustomerTradeParameterType" instead of a string,
// but am not sure how to add this extra join inside this select?
}).ToList()
})
.Where(e => e.Id == find.Id);
The .Select on CustomerTradeParameterList is raising the following error:
Microsoft.Data.SqlClient.SqlException (0x80131904): Invalid column name 'CustomerTradeId'.
I understand EF core is attempting to define a column that it is unsure of, but I am not sure how to fix this? The correct column is TradeId.
Secondly, I have an additional question regarding joins inside a sub .Select. In the query above I have a comment outlining the question.
Appreciate any tips you can provide!

MVC viewmodel and a linq query

I finally (after 4 weeks) got a result for a MVC5 project and it went well.
Now I'm trying to "limit" the number of results and it's flagging an error:
'Stoopid' is a type, which is not valid in the given context
'Student' is a type, which is not valid in the given context
Here's the model:
namespace viewModelA
{
public class Teacher
{
public int TeacherId { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
public class Student
{
public int StudentId { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string EnrollmentNo { get; set; }
}
public class Stoopid
{
[Key]
public int StoopID { get; set; }
public DateTime stopDt { get; set; }
}
public class ViewModel
{
public IEnumerable<Teacher> Teachers { get; set; }
public IEnumerable<Student> Students { get; set; }
public IEnumerable<Stoopid> Stoopids { get; set; }
}
}
and this is the linq query - notice that Teacher is fine, but Student and Stoopid are NOT. And they are all in the same .cs file. Am I missing something?
var result = (from t in Teacher
join s in Student on t.TeacherId equals s.StudentId
join st in Stoopid on s.StudentId equals st.StoopID
where t.TeacherId == 2
select new
{
TeacherID= t.TeacherId,
Code = t.Code,
t.Name,
s.StudentId,
sCode =s.Code,
sName=s.Name,
stopDt= st.stopDt
})
Edit: I added the relevant code to the HomeController. I also ran this thru LINQPad5 and it works fine so I don't know what's the deal
HomeController
You're referencing the class names in your Linq query, which is why it is throwing that error. You need to reference the actual List objects instead.
var result = (from t in mymodel.Teachers
join s in mymodel.Students on t.TeacherId equals s.StudentId
join st in mymodel.Stoopids on s.StudentId equals st.StoopID
where t.TeacherId == 2
select new
{
TeacherID= t.TeacherId,
Code = t.Code,
t.Name,
s.StudentId,
sCode =s.Code,
sName=s.Name,
stopDt= st.stopDt
})

c# AutoMapper ProjectTo selects all nested object properties

Let's take such classes:
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
public string ExtraProp { get; set; }
}
public class Parent
{
public int Id { get; set; }
public string Text { get; set; }
public Child Child { get; set; }
public string ParentExtraProp { get; set; }
}
public class ChildVo
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ParentVo
{
public int Id { get; set; }
public string Text { get; set; }
public ChildVo Child { get; set; }
}
Automapper mapping:
Mapper.CreateMap<Child, ChildVo>();
//.ForSourceMember(x => x.ExtraProp, o => o.Ignore()); //does not help
//.IgnoreAllNonExisting(); //does not help
Mapper.CreateMap<Parent, ParentVo>();
and query in Linq to Nhibernate:
var test = Session.Query<Parent>()
.Where(x => x.Id == myId)
.ProjectTo<ParentVo>()
.ToList();
ProjectTo selects only columns (properties) which are defined in ParentVo (not all properties from Parent class) - that's great. But is selects all columns (properties) from my Child class, despite the fact that they are not defined in ChildVo.
Why does Automapper ignore my nested property mapping? Is it possible to use all defined mappings during projection?
While I'm not familiar with nhibernate, the same test you've performed here works fine in Entity Framework. In EF you can see the query which has been generated before executing it - try doing this and seeing if it shows the additional column.
public class TestContext : DbContext {
public DbSet<Parent> Parents { get; set; }
}
var query = testContext.Parents.ProjectTo<ParentVo>();
Console.WriteLine(query.ToString());
This produces the following output (note no ExtraProp):
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Text] AS [Text],
CASE WHEN ([Extent2].[Id] IS NOT NULL) THEN 1 END AS [C1],
[Extent1].[Child_Id] AS [Child_Id],
[Extent2].[Name] AS [Name]
FROM [dbo].[Parents] AS [Extent1]
LEFT OUTER JOIN [dbo].[Children] AS [Extent2] ON [Extent1].[Child_Id] = [Extent2].[Id]
This makes me think that the problem is not AutoMapper specifically, but without seeing the generated query it's hard to tell.

How can i write a linq query for multiple tables in entity model MVC4?

I have these tables in my entity model
dbo.Options
[OptionsId] [OptionName]
1 Color
2 Size
3 Fit
dbo.ProductAttributes:
[ProdcutAttributeId] [SKU] [OptionId] [Value]
3001 Shirt_1001 1 Grey
3002 Shirt_1001 2 S
3003 Shirt_1001 3 Regular
3004 Shirt_1002 1 Black
3005 Shirt_1002 2 M
3006 Shirt_1002 3 Slim
dbo.Products:
[ProductId [ProductName] [ProductDescription] [Stock] [ImageURL] [ProductType]
dbo.ProductSKU:
ID SKU ProductId Price ImageURL
2001 Shirt_1001 1001 12 C:\Users\Administrator\Desktop\Images\LongSleeveShirt.jpg
2002 Shirt_1002 1001 13 C:\Users\Administrator\Desktop\Images\LongSleeveShirtBlack.jpg
2003 Shirt_1003 1001 12 C:\Users\Administrator\Desktop\Images\LongSleeveShirtkhaki.jpg
2004 Shirt_1004 1001 13 C:\Users\Administrator\Desktop\Images\LongSleeveShirtOrange.jpg
2005 Tshirt_1001 1002 13 C:\Users\Administrator\Desktop\Images\PlainWhiteT.jpg
2006 Tshirt_1002 1002 12 C:\Users\Administrator\Desktop\Images\PrintedTBlue.jpg
2007 Tshirt_1003 1002 13 C:\Users\Administrator\Desktop\Images\PrintedTWhite.jpg
2008 Tshirt_1004 1002 12 C:\Users\Administrator\Desktop\Images\LongSleeveBlackT.jpg
So these are the table I have in my entity model, now I want to write a linq query where I will pass the productID as parameter and I should get the productid,productname,productdescription of the productid passed as a parameter, and every Sku that product has each option the sku has and imageURl of the SKU.
How can I write a linq query for this?
this is how my model looks
public class ProductItems
{
public long ProductID { get; set; }
public string ProductName { get; set; }
public string ProductDescription { get; set; }
public string ImageURL { get; set; }
public string SKU { get; set; }
public long OptionID { get; set; }
public string optionName { get; set; }
public string Value{ get; set; }
public ProductItems()
{
if (SKUs == null )
SKUs = new List<productSKU>();
}
public List<productSKU> SKUs { get; set; }
public List<options> oPTIONS { get; set; }
}
public class productSKU
{
public productSKU()
{
if (oPTIONS == null)
oPTIONS = new List<options>();
}
public string productsku { get; set;}
public string SKUImageURL { get; set;}
public List<options> oPTIONS { get; set; }
}
public class options
{
public long OptionID { get; set; }
public string OptionName { get; set;}
public string OptionValue { get; set;}
}
Now I want to bind prodcuname,description and prodid to ProductItems class and every sku details should be bound to ProductSku class and each SKuOption should be bound to options class
I should get these columns at last [ProductID ],[ProductName ],[ProductDescription ],[SKU],[OptionId],[OptionName],[Value],[ImageURL] at last what I need is ProductName,Description every SKU of the product,every option value and name of the product
this is waht i am trying to do but i am confused how to bind this to my model
var produ = from PS in products.ProductSKUs
join PA in products.ProductAttributes on PS.SKU equals PA.SKU
join p in products.Products on PS.ProductId equals p.ProductId
join o in products.Options on PA.OptionId equals o.OptionsId
where PS.ProductId==ID
select new ProductItems()
{
ProductID=p.ProductId,
ProductName=p.ProductName,
ProductDescription = p.ProductDescription,
i am stuck here what to do next from here can any one help me here or provide me soltuion will be much gratefull
Thanks to any one who tried to answer my question i worked on this and got the solution
any one who wants to refer this i am posting the solution here
private ProductEntities products = new ProductEntities();
public IEnumerable<ProductItems> GetProductDetail(long ID)
{
ProductItems items=new ProductItems();
List<ProductItems> objcollection=new List<ProductItems>();
var productdetail=from prod in products.Products where prod.ProductId==ID select new {productid=prod.ProductId,description=prod.ProductDescription,productname=prod.ProductName};
foreach(var detail in productdetail)
{
items.ProductID=detail.productid;
items.ProductName=detail.productname;
items.ProductDescription=detail.description;
var prodsku=from prodksu in products.ProductSKUs where prodksu.ProductId==ID select prodksu;
foreach(var sku in prodsku)
{
productSKU prdsk=new productSKU();
prdsk.productsku=sku.SKU;
prdsk.SKUImageURL=sku.ImageURL;
items.SKUs.Add(prdsk);
var opt = from PA in products.ProductAttributes
join O in products.Options on PA.OptionId equals O.OptionsId
where PA.SKU == prdsk.productsku
select new { OptionId = PA.OptionId, OptionValue = PA.Value, OptionName = O.OptionName };
foreach(var op in opt)
{
options obj=new options();
obj.OptionID=Convert.ToInt16(op.OptionId);
obj.OptionName = op.OptionName;
obj.OptionValue=op.OptionValue;
prdsk.oPTIONS.Add(obj);
}
objcollection.Add(items);
}
}
return objcollection;
}

EF 4.1 POCO query

I have this POCO and I want to return a list of the users in a particular company.
public class Company
{
public AccreditedCompany()
{
this.Branches = new HashSet<Branch>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity), ScaffoldColumn(false)]
public int CompanyId { get; set; }
public bool Active { get; set; }
public virtual ICollection<Branch> Branches { get; set; }
}
public class Branch
{
public Branch()
{
this.Users = new HashSet<User>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity), ScaffoldColumn(false)]
public int BranchId { get; set; }
public int CompanyId { get; set; }
public string Name { get; set; }
public string ContactName { get; set; }
public virtual Company Company { get; set;}
public virtual ICollection<User> Users { get; set; }
}
public class User
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity), ScaffoldColumn(false)]
public int UserId { get; set; }
public int BranchId { get; set; }
public string ComputerSN { get; set; }
public string CameraSN { get; set; }
public virtual Branch Branch { get; set; }
}
This is my LINQ query:
var company = (from u in objDataContext.Companies.Include(c=>c.Branches.Select(v=>v.Users))
where u.CompanyId == 8 select u).FirstOrDefault();
IQueryable<User> users = (from j in company.Branches select j.Users);
I have this compilation error on the second query:
Error 2 Cannot implicitly convert type
'System.Collections.Generic.IEnumerable>'
to 'System.Linq.IQueryable'. An explicit conversion exists (are
you missing a cast?)
I want to get a list of the users, similar to a plain SQL statement like
SELECT dbo.Users.* FROM Branches
INNER JOIN dbo.Users ON dbo.Branches.BranchId = dbo.Users.BranchId
INNER JOIN dbo.Companies ON dbo.Branches.CompanyId = dbo.Companies.CompanyId
WHERE (dbo.Companies.CompanyId = 8)
Thanks in advance.
Your user query could be:
IEnumerable<User> users = company.Branches.SelectMany(branch => branch.Users);
This will return all users in any branch of the company.
It looks to me like you could just use:
IQueryable<User> users = objDataContext.Users
.Where(u => u.Branch.CompanyId == 8);
I notice you have both Company and CompanyId on your Branch entity, though. That seems redundant, even though it simplifies this query slightly. You should be able to get rid of Branch.CompanyId and User.BranchId and just use the entity associations.

Categories

Resources