How to merge duplicate collections - c#

I am trying to merge duplicate meters and have come op with this method:
private IEnumerable<Meter> MergeDuplicateMeters(IEnumerable<Meter> meters)
{
var tmpMeters = meters.ToList();
var duplicates = tmpMeters
.GroupBy(m => m.MeterUID)
.Where(grp => grp.Count() > 1)
.ToList();
foreach (var duplicate in duplicates)
{
var meter1 = duplicate.FirstOrDefault();
var meter2 = duplicate.LastOrDefault();
tmpMeters.Remove(meter1);
tmpMeters.Remove(meter2);
if (meter2.GsmData != null)
{
if (meter1.GsmData == null)
{
meter1.GsmData = new List<GSMData>();
}
meter1.GsmData.AddRange(meter2.GsmData);
}
if (meter2.P2pMeterSession != null)
{
if (meter1.P2pMeterSession == null)
{
meter1.P2pMeterSession = new List<P2PMeterSession>();
}
meter1.P2pMeterSession.AddRange(meter2.P2pMeterSession);
}
tmpMeters.Add(meter1);
}
return tmpMeters;
}
the problem is that this way I can only merge one time but what if I want to merge every time a new list is read?

Related

LINQ XML C# remove where condition in loop

Trying to delete nodes under certain conditions. Basically if certain checkboxes are checked I give an extra query with WHERE statement to my IENumerable named upit. After the queries has been set im trying to delete them iterating through every one, but nothing gets deleted everytime.
XDocument X = XDocument.Load(#"Financije.xml");
var upit = X.Element("POPIS").Elements("PODACI");
if (mjesec.Checked) { upit = upit.Where(E => (Convert.ToInt32(E.Element("MJESEC").Value) == Convert.ToInt32(mjesecbox.Text))); }
if (godina.Checked) { upit = upit.Where(E => (Convert.ToInt32(E.Element("GODINA").Value) == Convert.ToInt32(godinabox.Text))); }
if (ime.Checked) { upit = upit.Where(E => (E.Element("IME").Value.ToString().ToLower().Contains(search.Text.ToString().ToLower()))); }
if (opis.Checked) { upit = upit.Where(E => (E.Element("OPIS").Value.ToString().ToLower().Contains(search.Text.ToString().ToLower()))); }
if (veceod.Checked) { upit = upit.Where(E => (Convert.ToInt32(E.Element("CIJENA").Value.ToString()) > Convert.ToInt32(iznos.Text.ToString()))); }
if (manjeod.Checked) { upit = upit.Where(E => (Convert.ToInt32(E.Element("CIJENA").Value.ToString()) < Convert.ToInt32(iznos.Text.ToString()))); }
foreach (var item in upit)
{
upit.Remove();
}
and this is my XML file
<?xml version="1.0" encoding="utf-8"?>
<POPIS>
<PODACI>
<IME>test</IME>
<CIJENA>200</CIJENA>
<DATUM>12.1.2019</DATUM>
<MJESEC>1</MJESEC>
<GODINA>2019</GODINA>
<OPIS>test123333</OPIS>
</PODACI>
<PODACI>
<IME>voda</IME>
<CIJENA>230</CIJENA>
<DATUM>12.4.2018</DATUM>
<MJESEC>4</MJESEC>
<GODINA>2018</GODINA>
<OPIS>yes123no</OPIS>
</PODACI>
<PODACI>
<IME>oops</IME>
<OPIS>nice</OPIS>
<CIJENA>3</CIJENA>
<MJESEC>5</MJESEC>
<GODINA>2018<GODINA/>
<DATUM>24.02.2019</DATUM>
</PODACI>
<PODACI>
<IME>test</IME>
<OPIS>123</OPIS>
<CIJENA>1</CIJENA>
<MJESEC>12</MJESEC>
<GODINA>2019<GODINA/>
<DATUM>24.02.2019</DATUM>
</PODACI>
</POPIS>
It's a bit unclear what you want to end up with, but I assume you want to exclude items where they fail at least one case where the checkbox is checked and that comparison you are doing fails. So below achieves it in one query:
var X = XDocument.Load("Financije.xml");
var upit = X.Element("POPIS").Elements("PODACI");
var toRemove = upit.Where(u =>
// If mjesec is not checked, skip the predicate, otherwise evaluate it.
(!mjesec.Checked || (Convert.ToInt32(u.Element("MJESEC").Value) == Convert.ToInt32(mjesecbox.Text)))
// *And* do the same for godina and the rest of checkboxes...
&& (!godina.Checked || (Convert.ToInt32(u.Element("GODINA").Value) == Convert.ToInt32(godinabox.Text)))
&& (!ime.Checked || (u.Element("IME").Value.ToString().ToLower().Contains(search.Text.ToString().ToLower())))
&& (!opis.Checked || (u.Element("OPIS").Value.ToString().ToLower().Contains(search.Text.ToString().ToLower())))
&& (!veceod.Checked || (Convert.ToInt32(u.Element("CIJENA").Value.ToString()) > Convert.ToInt32(iznos.Text.ToString())))
&& (!manjeod.Checked || (Convert.ToInt32(u.Element("CIJENA").Value.ToString()) < Convert.ToInt32(iznos.Text.ToString()))));
X.Element("POPIS").ReplaceAll(upit.Except(toRemove));
X.Save("Financije.xml");
Give it a try
XDocument X = XDocument.Load(#"Financije.xml");
var upit = X.Element("POPIS").Elements("PODACI");
//I‘m only on phone so please excuse, if I take the wrong Type. Assign to null, to prevent Compiler-Error
IEnumerable<XElement> upitPart= null;
if (mjesec.Checked) { upitPart = upit.Where(E => (Convert.ToInt32(E.Element("MJESEC").Value) == Convert.ToInt32(mjesecbox.Text))); }
if (godina.Checked) { upitPart = upitPart.Where(E => (Convert.ToInt32(E.Element("GODINA").Value) == Convert.ToInt32(godinabox.Text))); }
if (ime.Checked) { upitPart = upitPart.Where(E => (E.Element("IME").Value.ToString().ToLower().Contains(search.Text.ToString().ToLower()))); }
if (opis.Checked) { upitPart = upitPart.Where(E => (E.Element("OPIS").Value.ToString().ToLower().Contains(search.Text.ToString().ToLower()))); }
if (veceod.Checked) { upitPart = upitPart.Where(E => (Convert.ToInt32(E.Element("CIJENA").Value.ToString()) > Convert.ToInt32(iznos.Text.ToString()))); }
if (manjeod.Checked) { upitPart = upitPart.Where(E => (Convert.ToInt32(E.Element("CIJENA").Value.ToString()) < Convert.ToInt32(iznos.Text.ToString()))); }
if(upitPart != null)
{
foreach (var item in upitPart)
{
upit.Remove(item);
}
}

Acumatica: Ability to override DefaultEndpointImpl to add advanced custom logic to contract REST API

I'm wondering if it possible to override DefaultEndpointImpl.cs or add my own API logic in another file?
I'm struggling with a few API calls which require the logic in this file to be overridden or added to. For example I am able to create a purchase receipt for a PO via the api successfully, however I'm not able to add a "Transfer Receipt" purchase receipt in the same way.
I've included various non-standard fields to the API endpoints that reference the original transfer, transfer order and shipment but have been unsuccessful. The API calls succeeds but no lines are added. I've been able to get lines to update their quantity once generated but can't add or delete current lines.
The problem looks to stem from this code, which seems to add functionality that correctly handles adding Purchase order lines logic of the graph but doesn't do anything special for other receipt types.
[FieldsProcessed(new[] { "POLineNbr", "POOrderType", "POOrderNbr" })]
protected void PurchaseReceiptDetail_Insert(PXGraph graph, EntityImpl entity, EntityImpl targetEntity) {
var receiptEntry = (POReceiptEntry)graph;
var lineNbr = targetEntity.Fields.SingleOrDefault(f => f.Name == "POLineNbr") as EntityValueField;
var orderType = targetEntity.Fields.SingleOrDefault(f => f.Name == "POOrderType") as EntityValueField;
var orderNbr = targetEntity.Fields.SingleOrDefault(f => f.Name == "POOrderNbr") as EntityValueField;
bool insertViaAddPO = lineNbr != null && orderNbr != null && orderType != null;
if (!insertViaAddPO && (lineNbr != null || orderType != null || orderNbr != null)) {
throw new PXException(PO.Messages.POTypeNbrLineNbrMustBeFilled);
}
var detailsCache = receiptEntry.transactions.Cache;
if (insertViaAddPO) {
receiptEntry.filter.Cache.Remove(receiptEntry.filter.Current);
receiptEntry.filter.Cache.Insert(new POReceiptEntry.POOrderFilter());
var filter = receiptEntry.filter.Current; var state = receiptEntry.filter.Cache.GetStateExt(filter, "OrderType") as PXStringState;
if (state != null && state.AllowedLabels.Contains(orderType.Value)) {
orderType.Value = state.ValueLabelDic.Single(p => p.Value == orderType.Value).Key;
}
receiptEntry.filter.Cache.SetValueExt(filter, "OrderType", orderType.Value);
receiptEntry.filter.Cache.SetValueExt(filter, "OrderNbr", orderNbr.Value);
receiptEntry.filter.Update(filter);
var orders = receiptEntry.poLinesSelection.Select().Select(r => r.GetItem<POReceiptEntry.POLineS>());
var order = orders.FirstOrDefault(o => o.LineNbr == int.Parse(lineNbr.Value));
if (order == null) {
throw new PXException(PO.Messages.PurchaseOrderLineNotFound);
}
order.Selected = true;
receiptEntry.poLinesSelection.Update(order);
receiptEntry.Actions["AddPOOrderLine2"].Press();
} else {
detailsCache.Current = detailsCache.Insert();
}
}
After a lot of trial and error I have managed to get everything working as I need. However I'm concerned that since this is not documented information that it may be subject to change in the near future.
The methods in the class DefaultEndpointImpl are called via reflection. To add custom functionality for my default endpoint I have extended the default class and added the necessary attributes to my class and functions.
My custom class adds the following:
Overides the default PurchaseReceiptDetail_Insert function to add transfer receipt functionality.
Adds ReceiptDetail_Insert method to allow adding an IN receipt referencing
The first one was pretty straight forward and I'm happy with the outcome. The second one took a lot of time and debugging to get right, is hacky and probably doesn't work with serial tracked items. The reason it's taken so long is because there are many unknowns and I've essentially been guessing based on the code in the base class. For example I'm not even sure at which stage this function fires. It looks the functions completely override some other default logic which is invisible.
So take it or leave it! Maybe I will reach out to Acumatica to see if I can get more information.
using PX.Api;
using PX.Api.ContractBased;
using PX.Api.ContractBased.Models;
using PX.Data;
using PX.Objects.PO;
using PX.Objects.IN;
using System;
using System.Linq;
using PX.Objects.CM;
using PX.Objects.CS;
namespace AcuStock
{
[PXVersion("5.30.001", "AcuStock")]
[PXVersion("6.00.001", "AcuStock")]
[PXVersion("17.200.001", "AcuStock")]
public class AcuStockEndpointImpl : PX.Objects.DefaultEndpointImpl
{
[FieldsProcessed(new[] { "POLineNbr", "POOrderType", "POOrderNbr", "OrigLineNbr", "OrigRefNbr" })]
protected new void PurchaseReceiptDetail_Insert(PXGraph graph, EntityImpl entity, EntityImpl targetEntity){
var lineNbr = targetEntity.Fields.SingleOrDefault(f => f.Name == "OrigLineNbr") as EntityValueField;
var refNbr = targetEntity.Fields.SingleOrDefault(f => f.Name == "OrigRefNbr") as EntityValueField;
var receiptQty = targetEntity.Fields.SingleOrDefault(f => f.Name == "ReceiptQty") as EntityValueField;
var location = targetEntity.Fields.SingleOrDefault(f => f.Name == "Location") as EntityValueField;
var inventoryID = targetEntity.Fields.SingleOrDefault(f => f.Name == "InventoryID") as EntityValueField;
bool insertViaAddTR = lineNbr != null && refNbr != null;
var receiptEntry = (POReceiptEntry) graph;
if (insertViaAddTR){
receiptEntry.addReceipt.Cache.Remove(receiptEntry.addReceipt.Current);
receiptEntry.addReceipt.Cache.Insert(new POReceiptEntry.POReceiptLineS());
var filter = receiptEntry.addReceipt.Current;
receiptEntry.addReceipt.Cache.SetValueExt(filter, "OrigRefNbr", refNbr.Value);
receiptEntry.addReceipt.Cache.SetValueExt(filter, "OrigLineNbr", lineNbr.Value);
receiptEntry.addReceipt.Cache.SetValueExt(filter, "InventoryID", inventoryID.Value);
receiptEntry.addReceipt.Cache.SetValueExt(filter, "ReceiptQty", receiptQty.Value);
if (location != null)
receiptEntry.addReceipt.Cache.SetValueExt(filter, "LocationID", location.Value);
receiptEntry.addReceipt.Update(filter);
var lines = receiptEntry.addReceipt.Select().Select(r => r.GetItem<POReceiptEntry.POReceiptLineS>());
var line = lines.FirstOrDefault(o => o.OrigLineNbr == int.Parse(lineNbr.Value));
if (line == null){
throw new PXException(PX.Objects.PO.Messages.PurchaseOrderLineNotFound);
}
receiptEntry.addPOReceiptLine2.Press();
} else {
base.PurchaseReceiptDetail_Insert(graph, entity, targetEntity);
}
var allocations = (targetEntity.Fields.SingleOrDefault(f => string.Equals(f.Name, "Allocations")) as EntityListField).Value ?? new EntityImpl[0];
if (allocations.Any(a => a.Fields != null && a.Fields.Length > 0)){
// Remove automatically added allocation
if (receiptEntry.splits.Current != null){
receiptEntry.splits.Delete(receiptEntry.splits.Current);
}
}
}
[FieldsProcessed(new[] { "OrigLineNbr", "OrigRefNbr", "Quantity", "Location" })]
protected void ReceiptDetails_Insert(PXGraph graph, EntityImpl entity, EntityImpl targetEntity) {
var lineNbr = targetEntity.Fields.SingleOrDefault(f => f.Name == "OrigLineNbr") as EntityValueField;
var receiptQty = targetEntity.Fields.SingleOrDefault(f => f.Name == "Quantity") as EntityValueField;
var location = targetEntity.Fields.SingleOrDefault(f => f.Name == "Location") as EntityValueField;
var allocations = (targetEntity.Fields.SingleOrDefault(f => string.Equals(f.Name, "Allocations")) as EntityListField).Value ?? new EntityImpl[0];
var hasAllocations = allocations.Any(a => a.Fields != null && a.Fields.Length > 0);
var receiptEntry = (INReceiptEntry) graph;
string transferNbr = receiptEntry.receipt.Current.TransferNbr;
var detailsCache = receiptEntry.transactions.Cache;
if (lineNbr == null || transferNbr == null){
detailsCache.Current = detailsCache.Insert();
return;
}
INTran newtran = null;
decimal newtranqty = Decimal.Parse(receiptQty.Value);
decimal newtrancost = 0m;
receiptEntry.ParseSubItemSegKeys();
using (new PXReadBranchRestrictedScope())
{
foreach (PXResult<INTransitLine, INLocationStatus2, INTransitLineLotSerialStatus, INSite, InventoryItem, INTran> res in
PXSelectJoin<INTransitLine,
InnerJoin<INLocationStatus2, On<INLocationStatus2.locationID, Equal<INTransitLine.costSiteID>>,
LeftJoin<INTransitLineLotSerialStatus,
On<INTransitLine.transferNbr, Equal<INTransitLineLotSerialStatus.transferNbr>,
And<INTransitLine.transferLineNbr, Equal<INTransitLineLotSerialStatus.transferLineNbr>>>,
InnerJoin<INSite, On<INSite.siteID, Equal<INTransitLine.toSiteID>>,
InnerJoin<InventoryItem, On<InventoryItem.inventoryID, Equal<INLocationStatus2.inventoryID>>,
InnerJoin<INTran,
On<INTran.docType, Equal<INDocType.transfer>,
And<INTran.refNbr, Equal<INTransitLine.transferNbr>,
And<INTran.lineNbr, Equal<INTransitLine.transferLineNbr>,
And<INTran.invtMult, Equal<shortMinus1>>>>>>>>>>,
Where<INTransitLine.transferNbr, Equal<Required<INTransitLine.transferNbr>>, And<INTransitLine.transferLineNbr, Equal<Required<INTransitLine.transferLineNbr>>>>,
OrderBy<Asc<INTransitLine.transferNbr, Asc<INTransitLine.transferLineNbr>>>>
.Select(receiptEntry, transferNbr, lineNbr.Value))
{
INTransitLine transitline = res;
INLocationStatus2 stat = res;
INTransitLineLotSerialStatus lotstat = res;
INSite site = res;
InventoryItem item = res;
INTran tran = res;
if (stat.QtyOnHand == 0m || (lotstat != null && lotstat.QtyOnHand == 0m))
continue;
if (newtran == null) {
if (!object.Equals(receiptEntry.receipt.Current.BranchID, site.BranchID))
{
INRegister copy = PXCache<INRegister>.CreateCopy(receiptEntry.receipt.Current);
copy.BranchID = site.BranchID;
receiptEntry.receipt.Update(copy);
}
newtran = PXCache<INTran>.CreateCopy(tran);
newtran.OrigBranchID = newtran.BranchID;
newtran.OrigTranType = newtran.TranType;
newtran.OrigRefNbr = transitline.TransferNbr;
newtran.OrigLineNbr = transitline.TransferLineNbr;
newtran.BranchID = site.BranchID;
newtran.DocType = receiptEntry.receipt.Current.DocType;
newtran.RefNbr = receiptEntry.receipt.Current.RefNbr;
newtran.LineNbr = (int)PXLineNbrAttribute.NewLineNbr<INTran.lineNbr>(receiptEntry.transactions.Cache, receiptEntry.receipt.Current);
newtran.InvtMult = (short)1;
newtran.SiteID = transitline.ToSiteID;
newtran.LocationID = transitline.ToLocationID;
newtran.ToSiteID = null;
newtran.ToLocationID = null;
newtran.BaseQty = 0m;
newtran.Qty = 0m;
newtran.UnitCost = 0m;
newtran.Released = false;
newtran.InvtAcctID = null;
newtran.InvtSubID = null;
newtran.ReasonCode = null;
newtran.ARDocType = null;
newtran.ARRefNbr = null;
newtran.ARLineNbr = null;
newtran.ProjectID = null;
newtran.TaskID = null;
newtran.CostCodeID = null;
newtran.TranCost = 0m;
receiptEntry.splits.Current = null;
newtran = receiptEntry.transactions.Insert(newtran);
receiptEntry.transactions.Current = newtran;
if (receiptEntry.splits.Current != null)
{
receiptEntry.splits.Delete(receiptEntry.splits.Current);
}
}
if (hasAllocations){
newtranqty = 0m;
foreach (var allocation in allocations) {
var newsplitqty = allocation.Fields.SingleOrDefault(f => f.Name == "Quantity") as EntityValueField;
var newsplitlocation = allocation.Fields.SingleOrDefault(f => f.Name == "Location") as EntityValueField;
INTranSplit newsplit = this.addReceiptSplitLine(receiptEntry, stat, lotstat, transitline, newtran, item, Decimal.Parse(newsplitqty.Value), newsplitlocation.Value);
newtrancost += newsplit.BaseQty.Value * newsplit.UnitCost.Value;
newtranqty += newsplit.BaseQty.Value;
}
break;
} else {
INTranSplit newsplit = this.addReceiptSplitLine(receiptEntry, stat, lotstat, transitline, tran, item, newtranqty, null);
newtrancost += newsplit.BaseQty.Value * newsplit.UnitCost.Value;
newtranqty += newsplit.BaseQty.Value;
}
}
receiptEntry.UpdateTranCostQty(newtran, newtranqty, newtrancost);
}
}
[FieldsProcessed(new[] { "OrigLineNbr" })]
protected void ReceiptAllocations_Insert(PXGraph graph, EntityImpl entity, EntityImpl targetEntity) {
// no-op
}
private INTranSplit addReceiptSplitLine(INReceiptEntry receiptEntry, INLocationStatus2 stat, INTransitLineLotSerialStatus lotstat, INTransitLine transitline, INTran tran, InventoryItem item, Decimal qty, string location){
INTranSplit newsplit;
decimal newsplitqty;
if (lotstat.QtyOnHand == null)
{
newsplit = new INTranSplit();
newsplit.InventoryID = stat.InventoryID;
newsplit.IsStockItem = true;
newsplit.FromSiteID = transitline.SiteID;
newsplit.SubItemID = stat.SubItemID;
newsplit.LotSerialNbr = null;
newsplitqty = qty;
}
else
{
newsplit = new INTranSplit();
newsplit.InventoryID = lotstat.InventoryID;
newsplit.IsStockItem = true;
newsplit.FromSiteID = lotstat.FromSiteID;
newsplit.SubItemID = lotstat.SubItemID;
newsplit.LotSerialNbr = lotstat.LotSerialNbr;
newsplitqty = qty;
}
newsplit.DocType = receiptEntry.receipt.Current.DocType;
newsplit.RefNbr = receiptEntry.receipt.Current.RefNbr;
newsplit.LineNbr = tran.LineNbr;
newsplit.SplitLineNbr = (int)PXLineNbrAttribute.NewLineNbr<INTranSplit.splitLineNbr>(receiptEntry.splits.Cache, receiptEntry.receipt.Current);
newsplit.UnitCost = 0m;
newsplit.InvtMult = (short)1;
newsplit.SiteID = transitline.ToSiteID;
newsplit.PlanID = null;
newsplit.Released = false;
newsplit.ProjectID = null;
newsplit.TaskID = null;
if (location == null) {
newsplit.LocationID = lotstat.ToLocationID ?? transitline.ToLocationID;
} else {
receiptEntry.splits.SetValueExt<INTranSplit.locationID>(newsplit, location);
}
newsplit = receiptEntry.splits.Insert(newsplit);
newsplit.MaxTransferBaseQty = newsplitqty;
newsplit.BaseQty = newsplitqty;
newsplit.Qty = newsplit.BaseQty.Value;
receiptEntry.UpdateCostSubItemID(newsplit, item);
receiptEntry.SetCostAttributes(tran, newsplit, item, tran.OrigRefNbr);
newsplit.UnitCost = PXCurrencyAttribute.BaseRound(receiptEntry, newsplit.UnitCost);
receiptEntry.splits.Update(newsplit);
return newsplit;
}
}
}

Finding an item in a list in c#

The code below contains a foreach loop that loops through a list of string collection which contains XML. While enumerating through the collection, it reads the question and answer elements and adds them to the list collection. I need to ensure that no repeated question is added to the list collection.
The code below questionnaire.QuestionAnswers.Add(fataQuestionsAnswers) adds the elements to the list collection. The problem that I am facing is that the repeated questions are getting added to the list. I tried to put the following condition that is:
if (questionnaire.QuestionAnswers.Find(a => a.Question != fataQuestionsAnswers.Question) == null)
but that doesn't seem to work.
var fataQuestionnaireData = DbAccess.GetFatcaQuestionnaire(contactId);
if (fataQuestionnaireData != null)
{
var questionnaire = new FatcaQuestionnaire();
foreach (var fatcaQuestionnaire in fataQuestionnaireData)
{
//var QData = GetObjectFromStream<FatcaQuestionnaire>fataQuestionnaireData);
//FatcaQuestionnaire.Deserialize(fataQuestionnaireData);
XDocument doc = XDocument.Parse(fatcaQuestionnaire.ToString(CultureInfo.InvariantCulture));
// w.WriteLine("The value of doc" + doc);
doc.Descendants("QuestionAnswer").ToList().ForEach(questionAnswer =>
{
var fataQuestionsAnswers = new QuestionAnswers();
{
//var questionAnswer = qa.Element("QuestionAnswer");
var questionElement = questionAnswer.Element("Question");
if (questionElement != null )
fataQuestionsAnswers.Question = questionElement.Value;
//if (questionElement != null)
// w.WriteLine("The value of questionElement" + questionElement.Value);
var answerElement = questionAnswer.Element("Answer");
if (answerElement != null)
fataQuestionsAnswers.Answer = answerElement.Value;
//if (answerElement != null)
// w.WriteLine("The value of answerElement" + answerElement.Value);
var sqa = questionAnswer.Element("SubQuestionAnswer");
if (sqa != null)
{
var subQuestionElement = sqa.Element("Question");
if (subQuestionElement != null)
fataQuestionsAnswers.SubQuestionAnswer.Question = subQuestionElement.Value;
//if (subQuestionElement != null)
// w.WriteLine("The value of answerElement" + subQuestionElement.Value);
var subAnswerElement = sqa.Element("Answer");
if (subAnswerElement != null)
fataQuestionsAnswers.SubQuestionAnswer.Answer = subAnswerElement.Value;
//if (subQuestionElement != null)
// w.WriteLine("The value of answerElement" + subQuestionElement.Value);
}
if (questionnaire.QuestionAnswers.Find(a => a.Question != fataQuestionsAnswers.Question) == null)
questionnaire.QuestionAnswers.Add(fataQuestionsAnswers);
//fatcaQuestionsList.Add(fataQuestionsAnswers);
}
fatca.Questionnaire.Add(fataQuestionsAnswers);
});
}
}
You have your condition wrong, you are looking for questionanswers where the question does not match, you should be looking where they do match and checking that the result is null. (switch the != with ==)
It should be
if (questionnaire.QuestionAnswers.Find(a => a.Question == fataQuestionsAnswers.Question) == null)
However I would change it to Any() as it is a bit nearer and easier to read, it returns a true if one of the items in your list matches the condition that you specify.
if(!questionnaire.QuestionAnswers.Any(a => a.Question == fataQuestionAnswers.Question)) {
questionnaire.QuestionAnswers.Add(fataQuestionsAnswers);
}
Use Any instead
if(!questionnaire.QuestionAnswers.Any(a => a.Question == fataQuestionsAnswers.Question))
{
questionnaire.QuestionAnswers.Add(fataQuestionsAnswers);
}
Is it possible there's trailing spaces / casing differences?
if(!questionnaire.QuestionAnswers.Any(a => a.Question.Trim().Equals(fataQuestionsAnswers.Question.Trim(), StringComparison.OrdinalIgnoreCase)))
{
questionnaire.QuestionAnswers.Add(fataQuestionsAnswers);
}

LINQ "OR" in expression

Just trying to get a cleaner code on a delete method. I need to delete records from a database if a certain column value matches one of two columns in another table.
Is there a better way to delete multiple records, with a "OR"-like expression, so that I can have only one for each loop instead of the following two?
public static void DeleteStageById(int StageId, int ApplicationId)
{
using (IPEntities ip = IPEntities.New())
{
var stage = ip.mkStages;
var stageCultures = ip.appObjectCultures;
var stageStates = ip.mkStatesInStages;
foreach (var stageCulture in stageCultures.Where(sC => sC.ObjectCultureId == stage.Where(s => s.StageId == StageId && s.ApplicationId == ApplicationId).FirstOrDefault().OCId_Name))
{
stageCultures.DeleteObject(stageCulture);
}
foreach (var stageCulture in stageCultures.Where(sC => sC.ObjectCultureId == stage.Where(s => s.StageId == StageId && s.ApplicationId == ApplicationId).FirstOrDefault().OCId_Description))
{
stageCultures.DeleteObject(stageCulture);
}
...
ip.SaveChanges();
}
}
my linq would look like this one
var stage = ip.mkStages;
var stageCultures = ip.appObjectCultures;
var stageStates = ip.mkStatesInStages;
//store this result into a temp variable so it only needs to run once
var temp = stage.Where(s => s.StageId == StageId && s.ApplicationId == ApplicationId).FirstOrDefault();
if (temp != null)
{
foreach (var stageCulture in stageCultures.Where(sC => sC.ObjectCultureId == temp.OCId_Name || sC.ObjectCultureId == temp.OCId_Description))
{
stageCultures.DeleteObject(stageCulture);
}
...
ip.SaveChanges();
}
I recommend avoiding confusing expressions, but here you go:
foreach (var stageCulture in stageCultures.Where(sC => {
var v = stage.Where(s => s.StageId == StageId && s.ApplicationId == ApplicationId).FirstOrDefault();
return sC.ObjectCultureId == v.OCId_Name || sC.ObjectCultureId == v.OCId_Description;
})
{
stageCultures.DeleteObject(stageCulture);
}

optimising linq queries to incres

I have the the below linq queries searching a the same data table and was wondering if it would be possible to make one search and do the below for loops to add data to to the same variables so that it can make the system faster.
var sort = configurationData.AsEnumerable().Where(sorts => sorts.Field<String>("QuestionStartText") == question &&
sorts.Field<String>("slideNo") == Convert.ToString(slideNumber) )
.Select(sorted => sorted.Field<String>("SortByColumn")).Distinct().AsParallel();
var rowNeedAfterSort = configurationData.AsEnumerable().Where(sorts => sorts.Field<String>("QuestionStartText") == question &&
sorts.Field<String>("slideNo") == Convert.ToString(slideNumber))
.Select(sorted => sorted.Field<String>("NoOfRows")).Distinct().AsParallel();
var indexs = configurationData.AsEnumerable().Where(sorts => sorts.Field<String>("QuestionStartText") == question &&
sorts.Field<String>("slideNo") == Convert.ToString(slideNumber))
.Select(sorted => sorted.Field<String>("ColumnInExcel")).Distinct().AsParallel();
int p = 0;
int chartValue = 0;
foreach (string inedcies in indexs)
{
if (inedcies != null)
{
if (!inedcies.ToUpper().Equals("NULL"))
{
if (inedcies.Contains(','))
{
Array.Clear(valuesUsed, 0, valuesUsed.Length);
string[] index = inedcies.Split(',');
foreach (string a in index)
{
valuesUsed[p] = Convert.ToInt32(a);
p++;
}
}
else if (inedcies.Equals("7"))
{
Array.Clear(valuesUsed, 0, valuesUsed.Length);
valuesUsed[p] = Convert.ToInt32(inedcies);
}
else
{
chartValue = Convert.ToInt32(inedcies);
}
}
}
}
foreach (string sortedint in sort)
{
if (sortedint != null)
{
if (!sortedint.ToUpper().Equals("NULL"))
{
SortData2(sortedint);
sortedData = "true";
}
}
}
foreach (string rows in rowNeedAfterSort)
{
if (rows != null)
{
if (!rows.ToUpper().Equals("NULL"))
{
string[] values = rows.Split(' ');
rowCount = Convert.ToInt32(values[1]);
}
}
}
Once you clean up the below codesmell you will be able to see how/where you can take out the foreach loops.
foreach (string a in index)
{
valuesUsed[p] = Convert.ToInt32(a);
p++;
}
what assurances do we have that index.length < valuesUsed.length ?
Foreach (x in y)
{
if (x != null)
{
do something
}
}
More readable. You also do not need to check if an element is null in a foreach loop. The properties of the element may need to be checked, but not the element itself.
y.Foreach(x => do what you need here)

Categories