Combination of two conditions in .cs code - c#

Desc
I have a problem with the "where" instruction from the .cs code, I don't know how to use "and" there?
I tried
Code dont run, "and" dont exist
[HttpGet]
public ActionResult GetNumberDays(string mieciacValue, int rokValue)
{
var liczbaDni = _ecpContext.Miesiace.Where(x => x.Rok == rokValue and x => x.Miesiac == miesiacValue).Select(i => new
{
ObecnaIloscDni = i.IloscDni
});
return null;
}

Replace the and by &&. See the documentation for more Details.
eg:
[HttpGet]
public ActionResult GetNumberDays(string mieciacValue, int rokValue)
{
var liczbaDni = _ecpContext.Miesiace.Where(x => x.Rok == rokValue && x.Miesiac == miesiacValue).Select(i => new
{
ObecnaIloscDni = i.IloscDni
});
return null;
}

Related

Efficiently select a set of objects that have multi value keys

I have a ProductVersions model which has a multi part key, a int ProductId and a int VersionNum field.
The function below takes a list of simple Dto classes that are just these 2 fields with goal of returning a set full ProductVersion objects from the database that match.
Below is a less than efficient solution. I am expecting the incoming list to only between 2 to 4 items so its not too bad but I'd like to do better.
private async Task<List<ProductVersion>?> GetProductVersionsFromDto(IList<ProductVersionDto>? productVersionDtos)
{
List<ProductVersion>? productVersions = null;
if (productVersionDtos != null)
{
foreach (ProductVersionDto dto in productVersionDtos)
{
ProductVersion? productVersion = await myPortalDBContext.ProductVersions
.Where(pv => pv.ProductId == dto.ProductId && pv.VersionNum == dto.VersionNum)
.FirstOrDefaultAsync();
if (productVersion != null)
{
if (productVersions == null) productVersions = new List<ProductVersion>();
productVersions.Add(productVersion);
}
}
}
return productVersions;
}
I had consider something like this:
private async Task<List<ProductVersion>?> GetProductVersionsFromDto(IList<ProductVersionDto>? productVersionDtos)
{
List<ProductVersion>? productVersions = null;
if (productVersionDtos != null)
{
productVersions = await myPortalDBContext.ProductVersions
.Join(productVersionDtos,
pv => new { pv.ProductId, pv.VersionNum },
pvd => new { pvd.ProductId, pvd.VersionNum },
(pv, pvd) => pv)
.ToListAsync();
}
return productVersions;
}
but at runtime fails because the Join doesn't make sense. Anyone know of way to do this more efficiently with just a single round-trip into the dbContext?
Use FilterByItems extension and then you can generate desired query:
private async Task<List<ProductVersion>?> GetProductVersionsFromDto(IList<ProductVersionDto>? productVersionDtos)
{
if (productVersionDtos == null)
return null;
var productVersions = await myPortalDBContext.ProductVersions
.FilterByItems(productVersionDtos,
(pv, dto) => pv.ProductId == dto.ProductId && pv.VersionNum == dto.VersionNum, true)
.ToListAsync();
return productVersions;
}

An exception was thrown while attempting to evaluate a LINQ query parameter expression

I got error in the tittle. Probably i must control string.IsNullOrEmpty(searchString) but i didn't it. My code bellow. Please help me
Thank you everyone i solved this problem. Problem was not here. Prooblem in my route codes. for search is different i would write my route codes this
endpoints.MapControllerRoute(
name:"search",
pattern: "{search}",
defaults: new {controller="Shop",action="search"}
);
but not in from of pattern: "{search}
should be this pattern: "search"
Thank you to everyone who helped
public List<Product> GetSearchResult(string searchString)
{
using (var context = new ShopContext())
{
var products = context
.Products
.Where(i=> i.IsApproved && (i.Name.ToLower().Contains(searchString.ToLower()) || i.Description.ToLower().Contains(searchString.ToLower())))
.AsQueryable();
return products.ToList();
}
}
I would break this up as follows:
public List<Product> GetSearchResult(string searchString)
{
// What do you want to do if searchString is null or blank? (Pick one:)
// You could send back an empty result...
if (String.IsNullOrWhiteSpace(searchString))
return null;
// Or you could convert it to a blank string
if (searchString == null)
searchString = "";
List<Product> products = new List<Product>();
using (var context = new ShopContext())
{
products = context.Products.ToList();
}
// Always check for null and empty after going to the DB
if (products == null || products.count = 0)
return null;
// If we are still here, then we can finally do the search
List<Product> results = products.Where(i=> i.IsApproved &&
(i.Name != null && i.Name.ToLower().Contains(searchString.ToLower()) ||
(i.Description != null && i.Description.ToLower().Contains(searchString.ToLower())));
return results;
}
Note: I've not tested this and there may be syntax errors in the last LINQ statement with all of the ('s and )'s.
EDIT:
The example above will pull back ALL records in the Product table and then filter the results in-memory. If you want to avoid that, then I think this should work:
public List<Product> GetSearchResult(string searchString)
{
// What do you want to do if searchString is null or blank? (Pick one:)
// You could send back an empty result...
if (String.IsNullOrWhiteSpace(searchString))
return null;
// Or you could convert it to a blank string
if (searchString == null)
searchString = "";
using (var context = new ShopContext())
{
List<Product> products = context.Products.Where(i=> i.IsApproved &&
(i.Name != null && i.Name.ToLower().Contains(searchString.ToLower()) ||
(i.Description != null && i.Description.ToLower().Contains(searchString.ToLower()))).ToList();
return products;
}
}
The key difference between this and your OP is that we are checking for null's on Name and Description -- and I believe this does it in a way that EF can translate into a query.
Not a lot of information at hand but i assume the LINQ fails because a string is null.
Also why do you create a queryable of your results and then produce a list?
public List<Product> GetSearchResult(string searchString) {
static bool Contains(string a, string b) {
return a.ToLower().Contains(b.ToLower());
}
using (var context = new ShopContext()) {
return context
.Products
.Where(i => i.IsApproved)
.Where(i => i.Name is null ? false : Contains(i.Name, searchString)
|| i.Description is null ? false : Contains(i.Description, searchString))
.ToList();
}
}

C# Refactor code to make re-usable with generics

This is a very loaded question but I am new to using generics and want to become proficient using them and taking my C#/.NET skills to the next level. I created a data filter using multiple dropdowns. Before I break the below method into smaller encapsulated, single responsibility methods, I was hoping I could get some help.
My goal is to re-use this filter in many parts of our application. In order to do so I will have to add the "filter" methods to our common base EntityController and EntityRespository classes. Obviously I am going to have to make use of generics to accomplish this task. Can anyone give me some advice after looking at the below (ridiculously long) method?
[HttpPost("FilteredResults")]
[ProducesResponseType(typeof(PaginatedList<ProcessCard>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status403Forbidden)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
[ProducesDefaultResponseType]
[Produces("application/json")]
public async Task<IActionResult> GetFilteredBusinessProcesses([FromBody] List<FieldFilterCriteria> filterCriteriaList = null)
{
try
{
List<BusinessProcess> listOfCommonItems = new List<BusinessProcess>();
PaginatedList<BusinessProcess> paginatedListOfCommonItems = new PaginatedList<BusinessProcess>();
var orgIdGuid = filterCriteriaList[0]?.OrganizationId;
if (filterCriteriaList != null)
{
var results = repository.Find(null, a => a.OrganizationId == orgIdGuid);
foreach (FieldFilterCriteria filter in filterCriteriaList)
{
foreach (string value in filter?.FilterValues)
{
switch (filter.Field)
{
case "Department":
var dList = results?.Items.Where(x => x.OrganizationUnitId == Guid.Parse(value)).ToList();
listOfCommonItems.AddRange(dList);
break;
case "Status":
var sList = results?.Items.Where(x => x.Status == value).ToList();
listOfCommonItems.AddRange(sList);
break;
case "Priority":
var pList = results?.Items.Where(x => x.Priority == value).ToList();
listOfCommonItems.AddRange(pList);
break;
case "Owner":
var oList = results?.Items.Where(x => x.OwnerName == value).ToList();
listOfCommonItems.AddRange(oList);
break;
}
}
}
if (filterCriteriaList.Count == 1)
{
paginatedListOfCommonItems.Items = listOfCommonItems;
}
if (filterCriteriaList.Count > 1)
{
listOfCommonItems = listOfCommonItems.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x.Key).ToList();
paginatedListOfCommonItems.Items = listOfCommonItems;
}
var businessProcessCard = processCatalogManager.GetBusinessProcessCard(paginatedListOfCommonItems);
return Ok(businessProcessCard);
}
else
{
return Ok();
}
}
catch (Exception ex)
{
return ex.GetActionResult();
}
}

Field in Database Not updating while using SubmitChanges()

I'm trying to update 2 field in my database using Database Context
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ChangeDefaultUserLockingSetting(int PasswordAttempts, int DefaultLockingTime)
{
var defaultAccountSettings = new DefaultAccountSettingsDataContext();
var defaultLockoutTimeSpam = defaultAccountSettings.DefaultAccountSettings.Where(u=>u.id==1).Select(u=>u.DefaultAccountLockoutTimeSpan).First();
var maxFailedAccessAttemptsBeforeLockout = defaultAccountSettings.DefaultAccountSettings.Where(u => u.id == 1).Select(u=>u.MaxFailedAccessAttemptsBeforeLockout).First();
//foreach (int item in defaultLockoutTimeSpam)
{
defaultLockoutTimeSpam = DefaultLockingTime;
}
maxFailedAccessAttemptsBeforeLockout = DefaultLockingTime;
defaultAccountSettings.SubmitChanges();
return View("Index", loadAdministrationViewModel());
}
What I am doing wrong?
You need to try this code.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ChangeDefaultUserLockingSetting(int PasswordAttempts, int DefaultLockingTime)
{
var defaultAccountSettings = new DefaultAccountSettingsDataContext();
var defaultLockoutTimeSpam = defaultAccountSettings.DefaultAccountSettings.Where(u => u.id == 1).FirstOrDefault();
var maxFailedAccessAttemptsBeforeLockout = defaultAccountSettings.DefaultAccountSettings.Where(u => u.id == 1).FirstOrDefault();
//foreach (int item in defaultLockoutTimeSpam)
{
defaultLockoutTimeSpam.DefaultAccountLockoutTimeSpan = DefaultLockingTime;
}
maxFailedAccessAttemptsBeforeLockout.MaxFailedAccessAttemptsBeforeLockout = DefaultLockingTime;
defaultAccountSettings.SubmitChanges();
return View("Index", loadAdministrationViewModel());
}
I was modifying the values but not the Object
This is the proper way to do it :
public ActionResult ChangeDefaultUserLockingSetting(int PasswordAttempts, int DefaultLockingTime)
{
var defaultAccountSettings = new DefaultAccountSettingsDataContext();
var accountSettings = defaultAccountSettings.DefaultAccountSettings.First(u => u.id == 1);
//The object should be modified and not his local value
accountSettings.DefaultAccountLockoutTimeSpan = DefaultLockingTime;
accountSettings.MaxFailedAccessAttemptsBeforeLockout = PasswordAttempts;
defaultAccountSettings.SubmitChanges();
return View("Index", loadAdministrationViewModel());
}

Setting the value to null using LINQ in list of list

I have a class
public class ReceiptDisplayInfo
{
public string ReceiptItemFor{get;set;}
public string ReceiptItemCategory{get;set;}
public string ReceiptItemReference{get;set;}
public string ReceiptRowCategory{get;set;}
public string ReceiptAmount{get;set;}
}
I have a list
List<List<ReceiptDisplayInfo>> dataSourceToBind ;
My requirement : For every List , if ReceiptRowCategory="Payment" , I have to set the value of ReceiptItemForm,ReceiptItemCategory to blank or null in dataSourceToBind .
I am doing using for loop but this is not the most appreciated approach.
Please assist me in doing using LINQ/Lambda Expression.
dataSourceToBind.ForEach(x =>
{
var innerList = x;
innerList.ForEach(y =>
{
if (y.ReceiptRowCategory == "Payment")
{
y.ReceiptItemFor = null;
y.ReceiptItemCategory = null;
}
});
});
I guess just 2 ForEach calls would suffice, no need to use LINQ here. However, since the transformation logic is quite complicated, I think you should extract it as a method:
private void SomeMethod(ReceiptDisplayInfo info) { // please name this appropriately
if (info.ReceiptRowCategory == "Payment") {
info.ReceiptItemForm = null;
info.ReceiptItemCategory = null;
}
}
And then,
dataSourceToBind.ForEach(x => x.ForEach(SomeMethod));
You can use below code to achieve this-
((from l in list
where l.ReceiptItemCategory == "payment"
select new ReceiptDisplayInfo()
{
ReceiptItemFor = null,
ReceiptItemCategory = null,
ReceiptItemReference = l.ReceiptItemReference,
ReceiptRowCategory = l.ReceiptRowCategory,
ReceiptAmount = l.ReceiptAmount
}).Union(from l in list
where l.ReceiptItemCategory != "payment"
select l)).ToList();

Categories