Comparing tables in the controller - c#

I have 2 tables, one is Orders, that holds the address/list of products, and a returnDetails table. This is used when a user wants to return an Order. The returnDetails has the OrderId that is being returned.
How do I display a message only on the orders that have a return with the same OrderID? Currently only "processing" is displayed.
I used a view model to display the Orders with products.
Here is what I tried but I haven't got it working yet:
[Authorize]
public ActionResult Index(string date)
{
string currentUser = this.User.Identity.GetUserName();
List<T_shirt_Company_v3.ViewModels.MyOrdersViewModel> list = (from o in new TshirtStoreDB().Orders
.Where(o => o.Username == currentUser)
.OrderByDescending(o => o.OrderDate)
.Select(o => new MyOrdersViewModel()
{
OrderId = o.OrderId,
Address = o.Address,
FirstName = o.FirstName,
LastName = o.LastName,
City = o.City,
OrderDate = o.OrderDate,
PostalCode = o.PostalCode,
Total = o.Total,
HasBeenShipped = o.HasBeenShipped,
PostageList = o.PostageList,
Details = (from d in o.OrderDetails
select new MyOrderDetails
{
Colour = d.Product.Colour,
Quantity = d.Quantity,
Title = d.Product.Title,
UnitPrice = d.UnitPrice
}).ToList()
}).ToList() select o).ToList();
if (date != null)
{
DateTime today = DateTime.Now.AddDays(Convert.ToInt32(date) * -1);
return View(list.Where(x => x.OrderDate >= today).ToList());
}
//WORKING ON
var returnstats = db.Orders.Where(x => x.OrderId == x.returnDetails.OrderId).ToList();
if (returnstats != null)
{
ViewBag.returnstats = "Returning Item";
}
else
{
ViewBag.returnstats = "processing";
}
return View(list);
}

I think the problem is that you are not clear about what is the business logic for 'returnstats'. From the values of this variable you provide, it looks like it's for a SINGLE order instead of an order list. Here is a modified Index method for your reference:
[Authorize]
public ActionResult Index(Int32? days)
{
string currentUser = this.User.Identity.GetUserName();
var orders = db.Orders //assume db is something inherited from DbContext
.Where(o => o.UserName == currentUser)
.OrderByDescending(o => o.OrderDate);
if (days.HasValue)
{
var startingDate = DateTime.Now.AddDays((-1) * days.Value);
orders = orders.Where(o => o.OrderDate >= startingDate);
}
var orderList = orders.ToList();
var returnOrderIds = db.ReturnDetails.Select(detail => detail.OrderId).ToList();
//here you will need to check with business analyst staff what is the rule for 'returnstats'.
//The business logic here is that if there is at least one order whose OrderId is in the ReturnDetails
//the 'returnstats' is 'Returning Item' otherwise it's 'Processing'.
if (orderList.Any(o => returnOrderIds.Contains(o.OrderId))
{
ViewBag.returnstats = "Returning Item";
} else
{
ViewBag.returnstats = "processing";
}
var viewModels = ...//the source code to create Order ViewModel with variable orderList
return View(viewModels);
}

Related

Does not display data in linq C#

I have Linq which counts the goods, the problem is that the names that I pass, they do not work
ProductName, CompanyName, CustomerName,
Maybe there is a error in Linq?
It produces many anonymous methods that have these fields, but after ToList() everything does not work
public async Task<IEnumerable<SalesReportItem>> GetReportData(DateTime dateStart, DateTime dateEnd)
{
dateStart = new DateTime(2000, 1, 1);
var context = await _contextFactory.CreateDbContextAsync();
var queryable = context.SalesTransactionRecords.Join(
context.Products,
salesTransactionRecords => salesTransactionRecords.ProductId,
products => products.Id,
(salesTransactionRecords, products) =>
new
{
salesTransactionRecords,
products
})
.Join(context.Companies,
combinedEntry => combinedEntry.salesTransactionRecords.CompanyId,
company => company.Id,
(combinedEntry, company) => new
{
combinedEntry,
company
})
.Join(context.VendorCustomers,
combinedEntryAgain => combinedEntryAgain.combinedEntry.salesTransactionRecords.CustomerId,
vendorCustomer => vendorCustomer.Id,
(combinedEntryAgain, vendorCustomer) => new
{
CompanyName = combinedEntryAgain.company.Name,
CustomerName = vendorCustomer.Name,
ProductId = combinedEntryAgain.combinedEntry.products.Id,
ProductName = combinedEntryAgain.combinedEntry.products.Name,
combinedEntryAgain.combinedEntry.salesTransactionRecords.MovementType,
combinedEntryAgain.combinedEntry.salesTransactionRecords.Period,
combinedEntryAgain.combinedEntry.salesTransactionRecords.Quantity,
combinedEntryAgain.combinedEntry.salesTransactionRecords.Amount,
}).Where(x => x.Period >= dateStart && x.Period <= dateEnd)
.GroupBy(combinedEntryAgain => new
{
combinedEntryAgain.ProductId,
combinedEntryAgain.ProductName,
combinedEntryAgain.CompanyName,
combinedEntryAgain.CustomerName,
}
).Select(x => new SalesReportItem
{
ProductId = x.Key.ProductId,
Quantity = x.Sum(a => a.Quantity),
Amount = x.Sum(x => (x.MovementType == TableMovementType.Income ? x.Amount : -(x.Amount)))
});
var items = await queryable.ToListAsync();
return _mapper.Map<IEnumerable<SalesReportItem>>(items);
}
my mistake was that I did not specify the fields in the select, otherwise everything is buzzing, the upper code is working
Select(x => new SalesReportItem
{
ProductId = x.Key.ProductId,
ProductName = x.Key.ProductName,
CompanyName = x.Key.CompanyName,
CustomerName = x.Key.CustomerName,
Quantity = x.Sum(x => (x.MovementType == TableMovementType.Income ? x.Quantity : - x.Quantity)),
Amount = x.Sum(x => (x.MovementType == TableMovementType.Income? x.Amount: - x.Amount))
});
Thanks for the help
Hans Kesting

LinqToSQL returning IQueryable

My interface is returning a IQueryable. The model TemplatesAgent with a template and IEnumerable<Agent> object. In my DataService I am collecting all of the agents in the ListOfAgent. I am then selecting the agent that are within the templates using the AgentVersionKey. This is the error I am getting is it related to the IQueryable type?
ExceptionMessage": "Explicit construction of entity type 'OrderTemplateTool.Data.Agent' in query is not allowed.",
Interface
IQueryable<TemplatesAgent> GetTemplateAgentNameDiseaseName(string agent, string disease);
DataService
public IQueryable<TemplatesAgent> GetTemplateAgentNameDiseaseName(string agent, string disease)
{
//Common
var ListOfAgent = (from a in UnitOfWork.GetRepository<Agent>().Get(a => !a.IsDeleted && a.IsCurrentVersion)
select new Agent
{
VersionKey = a.VersionKey,
Name = a.Name,
RxNormId = a.RxNormId,
BrandNames = a.BrandNames
});
var TemplatesAgent = (from t in UnitOfWork.GetRepository<Template>().Get()
join r in UnitOfWork.GetRepository<Regimen>().Get() on t.Id equals r.TemplateId
join rp in UnitOfWork.GetRepository<RegimenPart>().Get() on r.Id equals rp.RegimenId
join re in UnitOfWork.GetRepository<RegimenEntry>().Get() on rp.Id equals re.RegimenPartId
where t.IsCurrentVersion
&& t.Status == 7
select new TemplatesAgent
{
Template = t,
Agent = ListOfAgent.Where(x => x.VersionKey == re.AgentVersionKey).ToList()
});
Model
public class TemplatesAgent
{
public Template Template { get; set; }
public IEnumerable<Agent> Agent { get; set; }
}
Controller
[HttpGet]
public IHttpActionResult TemplatesList(string key, string disease = null, string agent = null)
{
var result = TemplatesDataService.GetTemplateAgentNameDiseaseName(agent, disease)
.Where(
t =>
t.Template.IsCurrentVersion && t.Template.Status == (short)TemplateMode.Published)
.OrderBy(t => t.Template.TemplateIdMain)
.ThenBy(t => t.Template.TemplateIdNumeric)
.ThenBy(t => t.Template.TemplateIdAlt)
.ToList()
.Select(t => new
{
TemplateId = t.Template.TemplateId,
RegimenTitle = t.Template.Title,
CourseTitle = t.Template.GroupTitle,
GuidelineTitle = t.Template.GuideLineTitle,
DiseaseId = t.Template.ExternalDiseaseId,
DiseaseName = t.Template.DiseaseName
Agent = t.Agent(a => new
{
VersionKey = a.VersionKey,
Name = a.Name,
BrandNames = a.BrandNames,
RxNormId = a.RxNormId
}).ToList(),
})
.Distinct().ToList();
return Json(result);
}
It is telling you that you can't make a new Agent inside the query. Try this.
var agentRepo = UnitOfWork.GetRepository<Agent>().Get();
var ListOfAgent = (from a in agentRepo
where !a.IsDeleted && a.IsCurrentVersion
select a);
var TemplatesAgent = (from t in UnitOfWork.GetRepository<Template>().Get()
join r in UnitOfWork.GetRepository<Regimen>().Get() on t.Id equals r.TemplateId
join rp in UnitOfWork.GetRepository<RegimenPart>().Get() on r.Id equals rp.RegimenId
join re in UnitOfWork.GetRepository<RegimenEntry>().Get() on rp.Id equals re.RegimenPartId
where t.IsCurrentVersion
&& t.Status == 7
select new TemplatesAgent
{
Template = t,
Agent = ListOfAgent.Where(x => x.VersionKey == re.AgentVersionKey).ToList()
});
Controller
[HttpGet]
public IHttpActionResult TemplatesList(string key, string disease = null, string agent = null)
{
var result = TemplatesDataService.GetTemplateAgentNameDiseaseName(agent, disease)
.Where(
t =>
t.Template.IsCurrentVersion && t.Template.Status == (short)TemplateMode.Published)
.OrderBy(t => t.Template.TemplateIdMain)
.ThenBy(t => t.Template.TemplateIdNumeric)
.ThenBy(t => t.Template.TemplateIdAlt)
.Distinct().ToList();
return Json(result);
}

How to get two fields with the same Id

I need to send two fields with the same Id in Altair(GraphQl).
mutation{
createGoodsOrder(goodsorder: {
deliveryDate: "2019-10-10"
goodsOrderItems: [
{ orderItemId: 54 quantity: 1 costPerUnit: 1 goodType: INGREDIENT }
{ orderItemId: 54 quantity: 2 costPerUnit: 2 goodType: INGREDIENT }
# { orderItemId: 58 quantity: 2 costPerUnit: 2 goodType: INGREDIENT }
]
}){
id
}
}
When I execute mutation, model contains both fields with the same Id but when I make Fetch, it returns only the first one. If It is not the same, Fetch returns both fields. How can I get both fields with the same Id?
var orderIngredients = _repository.Fetch<Ingredient>(e => model.GoodsOrderItems.Any(g => g.OrderItemId == e.Id)).ToList();
var orderIngredients = _repository.Fetch<Ingredient>(
e => e.IngredientType.PlaceId == model.PlaceId
&& model.GoodsOrderItems.Any(g => g.OrderItemId == e.Id && g.GoodType == GoodsTypes.Ingredient))
.Select(e => new GoodsOrderIngredientCreateModel
{
IngredientId = e.Id,
Quantity = model.GoodsOrderItems.First(i => i.OrderItemId == e.Id).Quantity,
CostPerUnit = model.GoodsOrderItems.First(i => i.OrderItemId == e.Id).CostPerUnit,
TotalPrice = model.GoodsOrderItems.First(i => i.OrderItemId == e.Id).Quantity *
model.GoodsOrderItems.First(i => i.OrderItemId == e.Id).CostPerUnit,
GoodType = GoodsTypes.Ingredient
}).Select(v => new GoodsOrderIngredient
{
Id = v.Id,
IngredientId = v.IngredientId,
Quantity = v.Quantity,
CostPerUnit = v.CostPerUnit,
TotalPrice = v.TotalPrice
}).ToList();
Mutation:
mutation.Field<GoodsOrderType>(
name: "createGoodsOrder",
arguments: new QueryArguments(
new QueryArgument<NonNullGraphType<GoodsOrderCreateInput>> { Name = nameof(GoodsOrder).ToLower() }
),
resolve: context =>
{
if (context.UserContext is GraphQLUserScopedContext userContext)
{
var goodsOrderService = userContext.ServiceScope.ServiceProvider.GetRequiredService<IVendorService>();
var model = context.GetArgument<GoodsOrderCreateModel>(nameof(GoodsOrder).ToLower());
model.PlaceId = userContext.User.PlaceId;
model.NetworkId = userContext.User.NetworkId;
var goodsOrder = goodsOrderService.CreateGoodsOrder(model);
return goodsOrder;
}
else
throw new ExecutionError(Constants.ErrorCodes.WrongUserContext);
}).RequireAuthorization(PermissionsRequirement
.CreateForPermissionSetAll(
new Dictionary<NetworkPermissions, PermissionLevels>
{ {NetworkPermissions.ERP_Cumulative, PermissionLevels.EditCreate} }));
I don't know c# but probably you don't need intermediate types
var orderIngredients = _repository.Fetch<Ingredient>(
e => e.IngredientType.PlaceId == model.PlaceId
&& model.GoodsOrderItems.Any(g => g.OrderItemId == e.Id && g.GoodType == GoodsTypes.Ingredient))
.Select(v => new GoodsOrderIngredient
{
Id = v.Id,
IngredientId = v.IngredientId,
Quantity = v.Quantity,
CostPerUnit = v.CostPerUnit,
TotalPrice = v.Quantity * v.CostPerUnit
}).ToList();
PS. If GoodsOrderIngredientCreateModel (for create mutation?) contains TotalPrice then total calculations are already in DB ?

The entity or complex type cannot be constructed in a LINQ to Entities query

On our online billing application, we give a billing summary of what bills the customer received and the payments they made.
In order for this to work, I have to first pull the payments then match them to the bills. So I have do something like:
foreach (BillPaymentSummary payment in billPayments)
{
DateTime dt = payment.DueDate;
// Debug errors on this next line
var summary = (from a in db.BillHistories
where a.CustomerId == customerNumber && a.DueDate == dt && a.Type == "BILL"
select new BillSummary
{
Id = a.Id,
CustomerId = a.CustomerId,
DueDate = a.DueDate,
PreviousBalance = a.PreviousBalance.Value,
TotalBill = a.TotalBill.Value,
Type = a.Type,
IsFinalBill = a.IsFinalBill
}).SingleOrDefault();
if (summary != null)
{
summary.PayDate = payment.PaidDate;
summary.AmountPaid = payment.AmountPaid;
returnSummaries.Add(summary);
}
else
{
summary = (from a in db.BillHistories
where a.CustomerId == customerNumber && a.DueDate == payment.DueDate && a.Type == "ADJ "
select new BillSummary
{
Id = a.Id,
CustomerId = a.CustomerId,
DueDate = a.DueDate,
PreviousBalance = a.PreviousBalance.Value,
TotalBill = a.TotalBill.Value,
Type = a.Type,
IsFinalBill = a.IsFinalBill
}).SingleOrDefault();
if (summary != null)
{
summary.PayDate = payment.PaidDate;
summary.AmountPaid = payment.AmountPaid;
returnSummaries.Add(summary);
}
}
}
I have been playing with this, but no matter what I do, I get the following error message:
The entity or complex type 'UtilityBill.Domain.Concrete.BillSummary' cannot be constructed in a LINQ to Entities query.
Is it because I am running queries within queries? How can I get around this error?
I have tried searching Google for an answer and see many answers, but none of them seem to explain my problem.
You cannot project onto a mapped entity. You would have to call ToList() before doing your mapping.
Or better yet, change to the following (calling FirstOrDefault will execute the query and allow you to populate your object):
var summary = db.BillHistories.FirstOrDefault(a => a.CustomerId == customerNumber && a.DueDate == dt && a.Type == "BILL").Select(x => new BillSummary
{
Id = a.Id,
CustomerId = a.CustomerId,
DueDate = a.DueDate,
PreviousBalance = a.PreviousBalance.Value,
TotalBill = a.TotalBill.Value,
Type = a.Type,
IsFinalBill = a.IsFinalBill
});
To decouple yourself from the Entity Framework you may want to also consider using a different model class to return instead of the Entity Framework model.
What I ended up doing was:
foreach (BillPaymentSummary payment in billPayments)
{
var data = db.BillHistories.Where(b => b.CustomerId == customerNumber && b.DueDate == payment.DueDate && b.Type == "B").FirstOrDefault();
if (data != null) // There is a bill history
{
returnSummaries.Add(new BillSummary
{
Id = data.Id,
CustomerId = data.CustomerId,
DueDate = data.DueDate,
PreviousBalance = data.PreviousBalance,
TotalBill = data.TotalBill,
Type = (data.Type.Trim() == "B" ? "BILL" : (data.Type == "A" ? "ADJ" : "")),
IsFinalBill = data.IsFinalBill,
PayDate = payment.PaidDate,
AmountPaid = payment.AmountPaid
});
}
else // No bill history record, look for an adjustment
{
data = db.BillHistories.FirstOrDefault(b => b.CustomerId == customerNumber && b.DueDate == payment.DueDate && b.Type == "A");
if (data != null)
{
returnSummaries.Add(new BillSummary
{
Id = data.Id,
CustomerId = data.CustomerId,
DueDate = data.DueDate,
PreviousBalance = data.PreviousBalance,
TotalBill = data.TotalBill,
Type = (data.Type.Trim() == "B" ? "BILL" : (data.Type == "A" ? "ADJ" : "")),
IsFinalBill = data.IsFinalBill,
PayDate = payment.PaidDate,
AmountPaid = payment.AmountPaid
});
}
}
db.SaveChanges();
}

Most efficient way of loading data into LINQ object for search result type method

I currently have the following:
public IEnumerable<News> NewsItems
{
get { return from s in News.All() where s.Description.Contains(SearchCriteria) || s.Summary.Contains(SearchCriteria) select s; }
}
The problem is I only need to return the one property that actually has the data as well as the Title property, something similar to.
return from s in News.All() where s.Description.Contains(SearchCriteria) || s.Summary.Contains(SearchCriteria) select new {Title = s.Title, Data = //Description or Summary containing the data
How do I determine which one contains the search query?
UPDATE: I have this but it obviously hits the DB 3 times
var FoundInSummary = News.All().Any(x => x.Summary.Contains(SearchCriteria));
var FoundInDesc = News.All().Any(x => x.Description.Contains(SearchCriteria));
IEnumerable<NewsEventSearchResults> result = null;
if ((FoundInSummary && FoundInDesc) || (FoundInSummary))
{
result = (from s in News.All() where s.Summary.Contains(SearchCriteria) select new NewsEventSearchResults { Title = s.Title, Data = s.Summary, ID = s.ID }).AsEnumerable();
}
else if (FoundInDesc)
{
result = (from s in News.All() where s.Description.Contains(SearchCriteria) select new NewsEventSearchResults { Title = s.Title, Data = s.Description, ID = s.ID }).AsEnumerable();
}
return result;
UPDATE 2: Is this more efficent?
var ss = (from s in News.All() where s.Description.Contains(SearchCriteria) || s.Summary.Contains(SearchCriteria) select s).ToList();
List<NewsEventSearchResults> resultList = new List<NewsEventSearchResults>();
foreach (var item in ss)
{
bool FoundInSummary = item.Summary.Contains(SearchCriteria);
bool FoundInDesc = item.Description.Contains(SearchCriteria);
if ((FoundInSummary && FoundInDesc) || (FoundInSummary))
{
resultList.Add(new NewsEventSearchResults { Title = item.Title, Data = item.Summary, ID = item.ID });
}
else if (FoundInDesc)
{
resultList.Add(new NewsEventSearchResults { Title = item.Title, Data = item.Description, ID = item.ID });
}
}
What if they both contain the criteria? Or are they mutually exclusive? If so
Data = (s.Description != null ? s.Description : s.Summary)
I went with option 3

Categories