Question: I want to use LINQ and check if one of the CarNames is inside result1. Why result1 returns nothing but result2 works fine?
result2 returns nothing
IQueryable<Cars_Model> Query = await _services.GetAllCars();
string result1 = "Car,Truck,Van";
Query = Query.Where(x => x.CarsName.ToUpper().Contains(result1.ToUpper()));
result2 works fine
IQueryable<Cars_Model> Query = await _services.GetAllCars();
string result2 = "Car"; // this works fine
Query = Query.Where(x => x.CarsName.ToUpper().Contains(result2.ToUpper()));
other information
public class Cars_Model
{
public Int64 Id { get; set; }
public string CarsName{ get; set; }
}
Just judging by your data I think you intended to do this instead:
IQueryable<Cars_Model> Query = await _services.GetAllCars();
var expectedTypes = "Car,Truck,Van".ToUpper().Split(",");
Query = Query.Where(x => expectedTypes.Contains(x.CarsName.ToUpper()));
Related
The idea is that a Reference Number or Vendor can be passed to the logic and it spits back the query results for the search. I know i'm missing something.. Just can't see it..
The SQL query idea was as follows..
"SELECT ReferenceNumber, VendorName, RequisitionStatus, RequestedOn, sum(RequisitionQTY*RequisitionPrice) as Total FROM partrequisition where ReferenceNumber = 105543 Group By 'ReferenceNumber' "
Can anyone help?
I'm getting the following error:
CS0029 Cannot implicitly convert type
System.Collections.Generic.List<decimal?> to
System.Data.Entity.DbSet<PartsManagement.Models.partrequisition>
(contoller)
public ActionResult Index(RequisitionSearch searchModel)
{
var PartRequisitionInfoLogic = new PartRequisitionInfoLogic(); //This is where any business Logic goes
var Model = PartRequisitionInfoLogic.Getpartrequisitions(searchModel); //This is where it figures out what Search Query is
var RequisisionResults = Model.ToList();
}
(Business Logic)
private wsdpartsmanagementEntities9 db = new wsdpartsmanagementEntities9();
public IQueryable<partrequisition> Getpartrequisitions(RequisitionSearch searchModel)
{
var result = db.partrequisitions.AsQueryable();
if (searchModel != null)
{
if (searchModel.ReferenceNumber != 0 && searchModel.VendorID == 0)
result = result.Where(c => c.ReferenceNumber == searchModel.ReferenceNumber).GroupBy(c => c.ReferenceNumber)
.Select(g => g.Sum(item => item.RequisitionQTY * item.RequisitionPrice)) // For each group, calculate the sum
.ToList();
if (searchModel.ReferenceNumber == 0 && searchModel.VendorID != 0)
result = result.Where(c => c.VendorName == searchModel.VendorID).GroupBy(c => c.ReferenceNumber)
.Select(g => g.Sum(item => item.RequisitionQTY * item.RequisitionPrice))// For each group, calculate the sum
.ToList();
}
return result;
}
(ViewModel(s))
public class RequisitionSearch
{
public int? VendorID { get; set; }
public int? ReferenceNumber { get; set; }
public List<RequisitionResults> SearchResults { get; set; }
public RequisitionSearch()
{
this.SearchResults = new List<RequisitionResults>();
}
}
}
public class RequisitionResults
{
public int ReferenceID { get; set; }
[Display(Name = "Reference Number")]
public int ReferenceNumber { get; set; }
[Display(Name = "Vendor Name")]
public string VendorName { get; set; }
[Display(Name = "Requisition Status")]
public string RequisitionStatus { get; set; }
[Display(Name = "Requisition On")]
public DateTime RequestedOn { get; set; }
[DisplayFormat(DataFormatString = "{0:C}")]
[Display(Name = "Requisition Total")]
public decimal RequisitionTotal { get; set; }
}
Update.. The solution was to scrap the Business logic and replace it with (below) in the ActionResult. Works perfectly.
var result = db.partrequisitions.AsQueryable();
if (searchModel.ReferenceNumber != null || searchModel.VendorID != null)
{
result = result.Where(partrequisition => partrequisition.ReferenceNumber == searchModel.ReferenceNumber || partrequisition.VendorName == searchModel.VendorID);
}
else
{
result = result.Distinct();
}
var b = result.GroupBy(x => x.ReferenceNumber);
var c = b.Select(group => group.Sum(partRequistion => partRequistion.RequisitionQTY * partRequistion.RequisitionPrice));
And to access the query information, a couple of foreach loops..
Have a look at the following line carefully:
result = result.Where(c => c.VendorName == searchModel.VendorID)
.GroupBy(c => c.ReferenceNumber)
.Select(g => g.Sum(item => item.RequisitionQTY * item.RequisitionPrice))// For each group, calculate the sum
.ToList();
You are trying to return a List Of Decimal? values using the Sum method while your method's return type is IQueryable<partrequisition>. So what you need is either changing your method's return type to a List of Decimals? or change your query in order to fulfill what your method actually needs by returning an IQueryable of partrequisition.
If you had split your big query into smaller ones, and used the keyword var a lot less, then you would have seen your problem at compile time:
Alas you forgot to describe your class PartRequisition. From your code it looks similar to:
class PartRequisition
{
public int ReferenceId {get; set;}
public int ReferenceNumber {get; set;}
public decimal? RequisitionQty {get; set;}
public decimal? RequisitionPrice {get; set;}
// one of them might be not a decimal? but a decimal.
}
Your code:
IQueryable<PartRequisition> result = db.partrequisitions.AsQueryable();
result = result
.Where(partRequistion => partRequisition.ReferenceID == searchModel.ReferenceNumber)
.GroupBy(partRequistion => partRequistion.ReferenceNumber)
.Select(group => group.Sum(partRequistion =>
partRequistion.RequisitionQTY * partRequistion.RequisitionPrice))
.ToList();
Let's split this into smaller parts:
IQueryable<PartRequisition> result = ...
IQueryable<PartRequisition> a = result.Where(partRequistion => ... == ...);
IQueryable<IGrouping<int, PartRequisition>> b = a.GroupBy(
partRequistion => partRequistion.ReferenceNumber);
So b is a queryable sequence of groups. Every group has an integer property Key. Each group is also a sequence of PartRequistions, namely all PartRequisitions that have a value of ReferenceNumber equal to the Key.
In the Select, you take each group of your sequence of groups. From every element in this group (which is a PartRequisition) you multiply two decimal? properties, which gives us a decimal? result. After that you sum these results, using Sum<decimal?>
IQueryable<decimal?> c = b.Select(group => group.Sum(partRequistion =>
partRequistion.RequisitionQTY * partRequistion.RequisitionPrice)
Or in even smaller steps:
c is IQueryable>`
Every group is IGrouping<int, PartRequisition>
every partRequisition is a PartRequisition
every RequisitionQTY and RequisitionPrice are decimial?
the result of the multiplication is decimal?
the result of the Sum is decimal?
d is IQueryable
Finally:
List<decimal?> d = c.ToList();
result = d; // remember, result is an IQueryable<PartRequisition>
It is clear to see that you can't assign a List<decimal?> to an IQueryable<PartRequisition>, which was exactly what the error said:
CS0029 Cannot implicitly convert type List to DbSet
Back to your problem
You descirbed a class RequistionResult that you didn't use in method GetRequisitions.
Can it be that you don't want to return an IQueryable<PartRequistions>
but an IQueryable<RequisitionResult>,
where property RequisitionTotal is your calculated Sum?
public IQueryable<RequisitionResult> GetRequisitions(...)
{
IQueryable<PartRequisition> partRequisitions = db.partrequisitions.AsQueryable();
if (searchModel != null)
{
if (searchModel.ReferenceNumber != 0 && searchModel.VendorID == 0)
{
partRequisitions = partRequisitions.Where(...);
}
else if (searchModel.ReferenceNumber == 0 && searchModel.VendorID != 0)
{
partRequisitions = partRequisitions.Where(...);
}
// else use all PartRequisitions
}
else
{
// TODO: decide what to return if searchModel is null, for example
partRequisitions = IQueryable.Empty<PartRequisition>();
// or use all PartRequisitions
}
// from the remaining set of PartRequisitions, convert to RequisitionResults:
IQueryable<RequisitionResult> requisitionResults = partRequisitions
.GroupBy(partRequisition => partRequisition.ReferenceNumber,
// parameter ResultSelector: take each ReferenceNumber and all PartRequisitions
// with this ReferenceNumber to make one new RequisitionResult
(referenceNumber, partRequisitionsWithThisReferenceNumber) => new RequisitionResult
{
RequisitionTotal = partRequisitionsWithThisReferenceNumber
.Select(partRequisition => partRequisition.RequisitionQty * partRequisition.RequisitionPrice)
.Sum(),
// fill other properties
...
});
return requisitionResults;
}
I have two linq queries in my controller that are both designed to return a string. However, my view displays the entire SQL query generated from the Linq query.
Model:
public class DummyClass
{
public string myMessage { get; set; }
public string myInitials { get; set; }
}
Controller:
public ActionResult EmployeeSignature()
{
using (MessageInfo db = new MessageInfo())
{
var message = db.SiteMessage_MyPay
.Where(x => x.active)
.Select(x => x.msgText).ToString();
using (DocumentReviewed database = new DocumentReviewed())
{
var document = database.Document_Reviewed
.Where(x => x.FileNumber == "whatever")
.Select(x => x.Initials).ToString();
var model = new DummyClass()
{
myMessage = message,
myInitials = document
};
return View(model);
}
}
}
View:
#model MyPayTC.Models.DummyClass
#{
ViewBag.Title = "EmployeeSignature";
}
#Model.myInitials
#Model.myMessage
Website displays:
SELECT [Extent1].[Initials] AS [Initials]
FROM [dbo].[Document_Reviewed] AS [Extent1]
WHERE '105057' = [Extent1].[FileNumber]
Instead of using .ToString( ), you should use .FirstOrDefault(), ToList(), etc like this:
var message = db.SiteMessage_MyPay
.Where(x => x.active)
.Select(x => x.msgText).FirstOrDefault();
Or, if you want to retrieve some columns, you can use ToArray() or ToList().
I have an entity like this:
public class Event
{
public string Code;
public DateTimeOffset DateTime;
}
I want to filter by Code and then group by DateTime.Date. I tried this:
var results = session
.Query<Event>()
.Where(e => e.Code == "123")
.GroupBy(e => e.DateTime.Date)
.ToList();
But I get the following error:
Raven.Client.Exceptions.InvalidQueryException: Field 'Code' isn't neither an aggregation operation nor part of the group by key
Query: from Events group by DateTime.Date where Code = $p0
Parameters: {"p0":"123"}
It can be seen from the resulting query that the where clause is being added after the group by clause, which explains the error.
So how do I perform this query in RavenDB?
EDIT:
The code "123" that I used was just an example. I need it to be a variable that is passed to the query, like this:
var results = session
.Query<Event>()
.Where(e => e.Code == code)
.GroupBy(e => e.DateTime.Date)
.ToList();
To start with, learn about the dynamic aggregation query syntax in:
https://demo.ravendb.net/demos/auto-indexes/auto-map-reduce-index
But, in your case you need to define a Static Map-Reduce Index to calculate this for you:(Sum up the number of (filtered) documents per unique Date)
i.e.
public class Result
{
public string Date { get; set; }
public int NumberOfDocs { get; set; }
}
Map = events => from event in events
where event.Code == "123"
select new Result
{
Date = event.DateTime.Date
NumberOfDocs = 1
}
Reduce = results => from result in results
group result by result.Date into g
select new Result
{
Date = g.Key,
Count = g.Sum(x => x.NumberOfDocs )
}
==> Learn about Static Map-Reduce Index in:
https://demo.ravendb.net/demos/static-indexes/map-reduce-index
Follow the detailed Walkthrough..
----------
Update:
You can use the following map-reduce index that aggregates the number of documents per Code & Date 'couple', and then you can query with 'Code'
public class Result
{
public string Code { get; set; }
public string Date { get; set; }
public int NumberOfDocs { get; set; }
}
Map = events => from event in events
select new Result
{
Code = event.Code
Date = event.DateTime.Date
NumberOfDocs = 1
}
Reduce = results => from result in results
group result by new
{
result.Code,
result.Date
}
into g
select new Result
{
Code = g.Key.Code
Date = g.Key.DateTime.Date,
NumberOfDocs = g.Sum(x => x.NumberOfDocs )
}
and then query
List<Result> queryResults = session.Query< Result, <Index_Name> >()
.Where(x => x.Code == "some-code-number")
.ToList();
and then you can also do in your code
queryResults.GroupBy(x => x.Date)
Consider the following classes:
public class Recipe
{
public string Id { get; set; }
public ICollection<RecipeFacet> RecipeFacets { get; set; }
}
public class RecipeFacet
{
public string Id { get; set; }
public Facet Facet { get; set; }
public string RecipeId { get; set; }
}
public class Facet
{
public string Name { get; set; }
}
I need to improve an existing query. I was thinking of using Linq's deferred execution. How would I write a Linq query that returns only Recipes, that contains ALL Facets I specify in a list of Tuples?
This is the original code that loops through Recipes and its Facets. It works but it is slow if my intial results query has lots of Recipes.
IQueryable<Recipe> result; //assume we have data here
string query = "Cuisine:American+Recipe-Type:dinners";
IEnumerable<Tuple<string, string>> taxFacets = query
.Split(' ')
.Select(tf => tf.Split(':'))
.Select(tf => new Tuple<string, string>(tf[0], tf[1]))
.Distinct();
var recipeFacetCollection = result.Select(r => r.RecipeFacets).ToList();
var matchedRecipesIds = new List<string>();
var recIds = result.Select(r => r.Id).ToList();
// initially, include all recipes
matchedRecipesIds.AddRange(recIds);
// loop through each recipe's facet collection
foreach (var col in recipeFacetCollection)
{
// loop through the tax facets from the query
foreach (var tf in taxFacets)
{
var exists = col.Any(f => f.Facet.Name.Equals(tf.Item2, StringComparison.OrdinalIgnoreCase));
// remove any recipe that is missing a facet
if (!exists)
{
matchedRecipesIds.Remove(col.First().RecipeId);
}
}
}
result = result.Where(r => matchedRecipesIds.Contains(r.Id));
How can I have a nice Linq query with deferred execution?
UPDATE::
Turning my Tuple into a List allows me to do this. But this query doesn't return any of my records.
This is my criteria:
Recipes, that have a collection of RecipeFacts, that contains Facets that have Name = "American" AND Name = "dinners".
var listFacets = new List<string>()
{
"American",
"dinners"
};
result = result
.Where(r => r.RecipeFacets
.All(f => !listFacets.Any(t => t.Equals(f.Facet.Name, StringComparison.OrdinalIgnoreCase))));
Your query logic selects all recipes whose facets don't exist in listFacets.
#Hung's logic is closer but selects recipes that have all of their facets in listFacets
I think that you want to select all recipes that contain all listFacets.
Simplifying the example to use lists of strings:
var listFacets = new[] { "a", "d" };
var recipes = new[] { new[] { "a" },
new[] { "a", "d" },
new[] { "a", "d", "e" },
new[] { "x" }
};
// correct query, returns 2 results ad and ade
var result = recipes.Where(r => listFacets.All(f => r.Any(rf => rf == f)));
// original incorrect query, returns x
var result2 = recipes.Where(r => r.All(f => !listFacets.Any(rf => rf == f)));
I am not quite sure cause your code block is quite long but here is what I can come up with
result = result.Where(r => r.RecipeFacets.All(f => taxFacets.Any(t => t.Item1.Equals(f.Facet.Name))));
Let me know if it helps or not
Remove the exclamation from the clause in the check on the listFacets collection.
result = result.Where(r => r.RecipeFacets.All(f => listFacets.Any(t => t.Equals(f.Facet.Name, StringComparison
I got this from #Rimp's help.
WHERE - filter
ALL - Require that All values from listFacets
ANY - is in ANY of the Facets.
result = result
.Where(x => listFacets
.All(lf => x.RecipeFacets
.Any(f => f.Facet.Slug.Equals(lf, StringComparison.OrdinalIgnoreCase))));
I have used a lot of SQL in the past but am new to LINQ. I have the following query which selects the otherID from the relevant table successfully, however when I try to select multiple columns I am unable to do so.
This is my following query:
var getQ = db.Requests.Where(x => temp.Contains(x.carID)).Select(x => x.otherID).ToList();
I have tried
var getQ = db.Requests.Where(x => temp.Contains(x.carID)).Select(x => x.otherID && x.dayID).ToList();
I am unable to get it to work, any help appreciated, thanks
You can use anonymous type to return multiple columns
var getQ = db.Requests.Where(x => temp.Contains(x.carID))
.Select(x => new { OtherID = x.otherID, DayID = x.dayID).ToList();
You can make a custom class, as the anonymous type could not be returned from method.
class YourClass
{
public int OtherID { get; set; }
public int DayID { get; set; }
}
var getQ = db.Requests.Where(x => temp.Contains(x.carID))
.Select(x => new YourClass { OtherID = x.otherID, DayID = x.dayID).ToList();
make the change is the select statement:
var getQ = db.Requests.Where(x => temp.Contains(x.carID)).Select(x => new{x.otherID, x.dayID}).ToList();