I have an IList , I also have a method which checks if the item is already in list and if it is I need it to be deleted/ removed and add again.
private PurchaseItemViewModel CheckSessionPurchaseItemViewModel(long purchaseLevelId)
{
bool itemFound = false;
PurchaseItemViewModel purItem = new PurchaseItemViewModel();
foreach (var item in UserSession.UserDataPurchaseItems)
{
if (item.PurchaseLevelId == purchaseLevelId)
{
itemFound = true;
purItem.Note = item.Note;
purItem.PurchaseAmount = item.PurchaseAmount;
purItem.PurchaseLevelId = item.PurchaseLevelId;
}
}
if (itemFound)
{
return purItem;
}
return null;
}
If it the above method finds the purchase item then it returns an object else null.
IList<PurchaseItemViewModel> purchaseSessionList = UserSession.UserDataPurchaseItems;
PurchaseItemViewModel pItem = CheckSessionPurchaseItemViewModel(levelId);
if(pItem != null)
{
purchaseSessionList.Remove(item);
}
So the issue is with the below line it is not removing the item , it does not even error.
**purchaseSessionList.Remove(item);**
Use this code for removing:
if(pItem != null) purchaseSessionList.Remove( purchaseSessionList.SingleOrDefault( s => s.PurchaseLevelId== levelId) );
IMHO you don't need to create pItem, would be enough to return false or true or item primary key.
Related
I am looking for tips to improve the readability of my code (which is written in C#). My main concern is usage of consecutive if statements and how should I replace them.
My code:
private Dictionary<Guid, CommerceMediaFileAssociation<T>> GetMediaToContentsAssociations<T>(ref bool stopSignaled, CatalogContentBase catalog, CultureInfo culture, Action<string> onStatusChanged = null)
where T : MediaData
{
IEnumerable<ContentReference> descendentReferences = _contentLoader.GetDescendents(catalog.ContentLink);
var associations = new Dictionary<Guid, CommerceMediaFileAssociation<T>>();
if (descendentReferences.Any())
{
var descendentProducts = _contentLoader.GetItems<BaseProduct>(descendentReferences, culture);
foreach (var product in descendentProducts)
{
if (stopSignaled)
{
onStatusChanged?.Invoke($"Reindexing canceled.");
break;
}
if (product is IAssetContainer assetContainer && (assetContainer?.CommerceMediaCollection?.Any() ?? false))
{
foreach (CommerceMedia media in assetContainer.CommerceMediaCollection)
{
PermanentLinkMap mediaLinkMap = _permanentLinkMapper.Find(media.AssetLink);
if ((mediaLinkMap?.Guid != null) && mediaLinkMap.Guid != Guid.Empty)
{
var productInformation = ProductUtilities.GetProductCategoriesAndPriority(product);
if (associations.TryGetValue(mediaLinkMap.Guid, out CommerceMediaFileAssociation<T> commerceMediaFileAssociations))
{
commerceMediaFileAssociations.Products.Add($"{product.ContentGuid.ToString()}||{product.MetaTitle}");
if (productInformation.Categories?.Any() ?? false)
{
foreach (string category in productInformation.Categories)
{
commerceMediaFileAssociations.ProductCategories.Add(category);
}
}
associations[mediaLinkMap.Guid] = commerceMediaFileAssociations;
}
else
{
var commerceMediaFileAssociation = new CommerceMediaFileAssociation<T>();
commerceMediaFileAssociation.Products.Add($"{product.ContentGuid.ToString()}||{product.MetaTitle}");
foreach (string category in productInformation.Categories)
{
commerceMediaFileAssociation.ProductCategories.Add(category);
}
associations.Add(mediaLinkMap.Guid, commerceMediaFileAssociation);
}
associations[mediaLinkMap.Guid].Priority = productInformation.Priority;
}
}
}
if (product is RockstarProduct rockstar)
{
var files = rockstar.Rockstar_Product_Product_Documents.FilteredItems.Select(x => x.GetContent() as IContentMedia) ?? new List<IContentMedia>();
foreach (var file in files)
{
PermanentLinkMap mediaLinkMap = _permanentLinkMapper.Find(file.ContentLink);
if ((mediaLinkMap?.Guid != null) && mediaLinkMap.Guid != Guid.Empty)
{
var productInformation = ProductUtilities.GetProductCategoriesAndPriority(product);
if (associations.TryGetValue(mediaLinkMap.Guid, out CommerceMediaFileAssociation<T> commerceMediaFileAssociations))
{
commerceMediaFileAssociations.Products.Add($"{product.ContentGuid.ToString()}||{product.MetaTitle}");
if (productInformation.Categories?.Any() ?? false)
{
foreach (string category in productInformation.Categories)
{
commerceMediaFileAssociations.ProductCategories.Add(category);
}
}
associations[mediaLinkMap.Guid] = commerceMediaFileAssociations;
}
else
{
var commerceMediaFileAssociation = new CommerceMediaFileAssociation<T>();
commerceMediaFileAssociation.Products.Add($"{product.ContentGuid.ToString()}||{product.MetaTitle}");
foreach (string category in productInformation.Categories)
{
commerceMediaFileAssociation.ProductCategories.Add(category);
}
associations.Add(mediaLinkMap.Guid, commerceMediaFileAssociation);
}
associations[mediaLinkMap.Guid].Priority = productInformation.Priority;
}
}
}
}
}
return associations;
}
How should I change it in order to make it clean, understandable and maintainable? Should I use guard clauses in this case?
You have a lot of code duplications. Some code parts are almost equivalent. It is easy to make them equal. This allows you extract them to another method.
Also, you have if-else statements where the else-part has a lot in common with the if-part where basically only the first statement differs (after having made the almost equal statements equal). You can extract these statements and execute them after the if-else. Then if-part becomes empty. You can invert the if-else and then drop the else part.
There is also no point in testing a collection with Any() before looping through it. If the collection is empty, the loop body will not be executed anyway.
The extracted method:
private void AddCategoriesAndProducts<T>(Dictionary<Guid, CommerceMediaFileAssociation<T>> associations, BaseProduct product, string link) where T : MediaData
{
PermanentLinkMap mediaLinkMap = _permanentLinkMapper.Find(link);
if (mediaLinkMap?.Guid != null && mediaLinkMap.Guid != Guid.Empty) {
var productInformation = ProductUtilities.GetProductCategoriesAndPriority(product);
if (!associations.TryGetValue(mediaLinkMap.Guid, out CommerceMediaFileAssociation<T> commerceMediaFileAssociations)) {
commerceMediaFileAssociations = new CommerceMediaFileAssociation<T>();
}
commerceMediaFileAssociations.Products.Add($"{product.ContentGuid}||{product.MetaTitle}");
if (productInformation.Categories != null) {
foreach (string category in productInformation.Categories) {
commerceMediaFileAssociations.ProductCategories.Add(category);
}
}
associations[mediaLinkMap.Guid] = commerceMediaFileAssociations;
associations[mediaLinkMap.Guid].Priority = productInformation.Priority;
}
}
The simplified method:
private Dictionary<Guid, CommerceMediaFileAssociation<T>> GetMediaToContentsAssociations<T>(ref bool stopSignaled, CatalogContentBase catalog, CultureInfo culture, Action<string> onStatusChanged = null)
where T : MediaData
{
IEnumerable<ContentReference> descendentReferences = _contentLoader.GetDescendents(catalog.ContentLink);
var associations = new Dictionary<Guid, CommerceMediaFileAssociation<T>>();
if (descendentReferences.Any()) {
var descendentProducts = _contentLoader.GetItems<BaseProduct>(descendentReferences, culture);
foreach (var product in descendentProducts) {
if (stopSignaled) {
onStatusChanged?.Invoke($"Reindexing canceled.");
break;
}
if (product is IAssetContainer assetContainer && assetContainer.CommerceMediaCollection != null) {
foreach (CommerceMedia media in assetContainer.CommerceMediaCollection) {
AddCategoriesAndProducts(associations, product, media.AssetLink);
}
}
if (product is RockstarProduct rockstar) {
var files = rockstar.Rockstar_Product_Product_Documents.FilteredItems.Select(x => x.GetContent() as IContentMedia) ?? new List<IContentMedia>();
foreach (var file in files) {
AddCategoriesAndProducts(associations, product, file.ContentLink);
}
}
}
}
return associations;
}
These methods are still relatively complex and could be split into even smaller methods. Methods like AddAssetProducts and AddRockStartProducts.
Im facing performance issue in below code in multiple foreach loops. First im getting a list of ReturnDetails and then based on detail id get the HandlingInfo object. Then based on value of action, update the ReturnsDetail Object again.
It take more than a minute for loading 3000 records of ReturnsDetail. While debugging locally, it runs for infinite amount of time.
Please let me know in anyway i can refactor this code .
Thanks for your help.
lstReturnsDetail = dcReturnsService.GetReturnDetailsInfo(header_id);
List<HandlingInfo> lstHandlingInfo = null;
foreach (ReturnsDetail oReturnsDetail in lstReturnsDetail)
{
using (DCReturns_Entities entities = new DCReturns_Entities())
{
lstHandlingInfo = entities.HandlingInfoes.Where(f => f.detail_id == oReturnsDetail.id).ToList();
if(lstHandlingInfo != null)
{
foreach (HandlingInfo oHandlingInfo in lstHandlingInfo)
{
if (oHandlingInfo.action == "DST")
{
oReturnsDetail.destroy += Convert.ToInt32(oHandlingInfo.qty);
}
else if (oHandlingInfo.action == "SHP")
{
oReturnsDetail.to_shop += Convert.ToInt32(oHandlingInfo.qty);
}
else if (oHandlingInfo.action == "RBX")
{
oReturnsDetail.in_stock += Convert.ToInt32(oHandlingInfo.qty);
}
}
}
}
oReturnsDetail.received_qty = oReturnsDetail.destroy + oReturnsDetail.to_shop + oReturnsDetail.in_stock;
}
dgReturnsDetail.DataSource = lstReturnsDetail.OrderByDescending(g => g.id).ToList();
Session[DCReturnsConstants.Returns_Detail_Entity] = lstReturnsDetail;
dgReturnsDetail.DataBind();
this is su-do code! but you should get the jist.
//modify this to return all of them into mem, and then filter on this...
//if it can not be done here then do below..
var lstReturnsDetail = dcReturnsService.GetReturnDetailsInfo(header_id);
//then create a list here which fetches all,
List<[type]> somelist
List<int> listId = lstReturnsDetail.select(x=>x.id).tolist();
using (var db = new DCReturns_Entities())
{
somelist = db.HandlingInfoes.Where(f => listId.Contains( f.detail_id)).ToList();
}
foreach (ReturnsDetail oReturnsDetail in lstReturnsDetail)
{
//performance issue is here
//using (DCReturns_Entities entities = new DCReturns_Entities())
//{
// lstHandlingInfo = entities.HandlingInfoes.Where(f => f.detail_id == oReturnsDetail.id).ToList();
//}
//insead fetach all before, into mem and filter from that list.
var lstHandlingInfo = somelist.Where(f => f.detail_id == oReturnsDetail.id).ToList();
//code ommited for reaablity
}
//code ommited for reaablity
I created a method where i take a random row from ma database and put it into new List, if the method will be used again, it will check if the random row was selected before and chose another one, like drawing without repetition.The program compile, but dont work. Can anyone tell me what i am doing wrong?
TABUEntities baza = new TABUEntities();
IList AlreadyChosen = new List<IList>();
public List<HASLA> RandomWords()
{
List<HASLA> dane = baza.HASLA.OrderBy(x => Guid.NewGuid()).Take(1).ToList();
if (AlreadyChosen.Contains(dane))
{
RandomWords();
}
AlreadyChosen.Add(dane);
return dane;
}
if (AlreadyChosen.Any(a=>a.SomeUniqueProperty == dane.SomeUniqueProperty))
You have to search by some unique property like Id to make sure you can find the object. Also if you want to use Contains then you will have to implement and override the IComparable interface and methods, or pass a custom comparer.
Try this
TABUEntities baza = new TABUEntities();
List<HASLA> AlreadyChosen = new List<HASLA>();
public List<HASLA> RandomWords()
{
List<HASLA> rw = new List<HASLA>();
rw.addRange(AlreadyChosen);
HASLA selectedObj = baza.HASLA.Where(y => !AlreadyChosen.Contains(y)).OrderBy(x => Guid.NewGuid()).Take(1).FirstOrDefault();
if ((selectedObj == null)) {
return rw;
} else {
if (AlreadyChosen.Contains(selectedObj)) {
return RandomWords();
} else {
AlreadyChosen.add(selectedObj);
return RandomWords();
}
}
}
I'm validating TextFields with a foreach loop with an if/else statement inside. This all happens inside a public virtual Boolean Method(). Only the first element is validated and I don't know why the rest is not validated.
How do I have to change my method so it will validate all the items in TextFieldList?
This is my method:
public virtual Boolean ValidateTextFields(){
foreach (UITextField item in TextFieldList) {
if (item.Text == "") {
item.AttributedPlaceholder = new NSAttributedString (item.Placeholder, foregroundColor: UIColor.Red);
return false;
} else {
return true;
}
}
return true;
}
EDIT:
I got it working but now I have another issue, I have multiple methods like ValidateTextFields and I check them like this:
if (ValidateTextFields() && ValidateEmail() ) {
Console.WriteLine ("CONTINUE TO NEXT SCREEN");
} else {
Console.WriteLine ("ERRORRRRRR");
}
Now if ValidateTextFields() is false then ValidateEmail() is never called so the EmailTextFields won't be validated. Only after ValidateTextFields() is true I can validate ValidateEmail(). Is there a way to call both methods at the same time and check if they are true?
Try this:
If have any invalid field the Method returns false, else if all fields is valid returns true.
public virtual Boolean ValidateTextFields(){
foreach (UITextField item in TextFieldList) {
if (item.Text == "") {
item.AttributedPlaceholder = new NSAttributedString (item.Placeholder, foregroundColor: UIColor.Red);
return false;
}
}
return true;
}
Or you can valid all itens to put a attributedplaceholder for each item and returns if has any invalid, like this:
public virtual Boolean ValidateTextFields(){
bool hasInvalidFields = false;
foreach (UITextField item in TextFieldList) {
if (item.Text == "") {
item.AttributedPlaceholder = new NSAttributedString (item.Placeholder, foregroundColor: UIColor.Red);
hasInvalidFields = true;
}
}
return !hasInvalidFields;
}
For your edit, to call all validates you can:
bool validTextFields = ValidateTextFields();
bool validEmails = ValidateEmail();
if ( validTextFields && validEmails) {
Console.WriteLine ("CONTINUE TO NEXT SCREEN");
} else {
Console.WriteLine ("ERRORRRRRR");
}
Your code will always return after the first element has been processed, whether it's valid or not.
What you probably want instead is to validate all elements and return afterwards:
var result = true;
foreach (UITextField item in TextFieldList) {
if (item.Text == "") {
item.AttributedPlaceholder =
new NSAttributedString (item.Placeholder, foregroundColor: UIColor.Red);
result = false;
}
}
return result;
You simply need to remember what to return in the end instead of returning immediately.
Is there a way to query an XmlSchema or XmlSchemaSet for a list of available tags/attributes at a certain point in the XML? So say my cursor is between <b> and </b> and my schema only allows for a <c/> element there, can I figure that out using anything built in to C#?
<tagset>
<a></a>
<b><!-- CURSOR IS HERE --></b>
</tagset>
There is a way, but the Xml Schema specification is complex so it will take some effort and a few hundred lines of code.
The GetExpectedParticles method of the .NET XmlSchemaValidator class is the key part to a solution. This uses the XmlSchemaSet, passed as an argument, to return a set of XmlSchemaObject instances.
Before you can call this method you need to build a node path to your cursor location which must include ancestor elements and their preceding siblings and also the preceding siblings at the current nesting level. This node path is used to set the context for the schema validator.
After GetExpectedParticles has been called you need to process the particles. For instance, check if each the expected particle is a member of a substitution group, and check whether the expected particle is a restricted simple type that's an enumeration.
It's probably best to separate out code that fetches expected elements and attributes respectively.
The following incomplete code snippet includes the GetExpectedParticles method call, this only caters for element tag content, not attributes:
public static List<XmlSchemaObject> XsdExpectedElements(XmlSchemaSet schemaSet,
List<NodeDescriptor> nodePath)
{
List<XmlSchemaObject> elementNames = new List<XmlSchemaObject>();
NameTable nt = new NameTable();
XmlNamespaceManager manager = new XmlNamespaceManager(nt);
XmlSchemaValidator validator = new XmlSchemaValidator(nt, schemaSet, manager, XmlSchemaValidationFlags.None);
// event handler sets validationErrorFound local field
validator.ValidationEventHandler += new ValidationEventHandler(validator_ValidationEventHandler);
validator.Initialize();
XmlSchemaInfo xsInfo = new XmlSchemaInfo();
int i = 0;
foreach (nodeDescriptor nameUri in nodePath)
{
validator.ValidateElement(nameUri.LocalName, nameUri.NamespaceUri, xsInfo);
if ((i >= siblingPosition && siblingPosition > -1) || nameUri.Closed)
{
validator.SkipToEndElement(null);
}
else
{
validator.ValidateEndOfAttributes(null);
}
i++;
}
XmlSchemaParticle[] parts = validator.GetExpectedParticles();
if (parts.Length == 0)
{
bool hasElements = true;
bool elementClosed = nodePath[nodePath.Count - 1].Closed;
if (elementClosed) // we're outside the element tags
{
hasElements = true;
}
else if (xsInfo.SchemaType is XmlSchemaSimpleType)
{
hasElements = false;
}
else
{
XmlSchemaComplexType xsCt = xsInfo.SchemaType as XmlSchemaComplexType;
XmlSchemaContentType xsContent = (XmlSchemaContentType)xsCt.ContentType;
if (xsContent == XmlSchemaContentType.TextOnly)
{
hasElements = false;
}
}
if (!hasElements)
{
expectedType = XmlEditor.expectedListType.elementValue;
if (xsInfo.SchemaElement != null)
{
elementNames.Add(xsInfo.SchemaElement);
}
}
return elementNames;
}
foreach (XmlSchemaObject xso in parts)
{
if (xso is XmlSchemaElement)
{
XmlSchemaElement xse = (XmlSchemaElement)xso;
if (subGroupList.ContainsKey(xse.QualifiedName))
{
List<XmlSchemaElement> xses = subGroupList[xse.QualifiedName];
foreach (XmlSchemaElement xseInstance in xses)
{
elementNames.Add(xseInstance);
}
}
else
{
elementNames.Add(xse);
}
}
else if (xso is XmlSchemaAny)
{
XmlSchemaAny xsa = (XmlSchemaAny)xso;
foreach (XmlSchema xs in schemaSet.Schemas())
{
if (xs.TargetNamespace == xsa.Namespace)
{
foreach (XmlSchemaElement xseAny in xs.Elements)
{
elementNames.Add(xseAny);
}
}
}
}
}
}
The following (incomplete) code snippet shows how to get expected enumerated values from a particle:
private List<string> ExpectedEnumValues(XmlSchemaObject xsso)
{
XmlSchemaSimpleType xst = null;
XmlSchemaComplexType xsCt = null;
List<string> values = new List<string>();
if (xsso == null)
{
return values;
}
if (xsso is XmlSchemaAttribute)
{
XmlSchemaAttribute xsa = (XmlSchemaAttribute)xsso;
xst = xsa.AttributeSchemaType;
}
else
{
XmlSchemaElement xse = (XmlSchemaElement)xsso;
XmlSchemaType gxst = xse.ElementSchemaType;
if (gxst is XmlSchemaSimpleType)
{
xst = (XmlSchemaSimpleType)gxst;
}
else if (gxst is XmlSchemaComplexType)
{
xsCt = (XmlSchemaComplexType)gxst;
}
else
{
return values;
}
}
if(xst != null)
{
if (xst.TypeCode == XmlTypeCode.Boolean)
{
values.Add("true");
values.Add("false");
}
else
{
ProcessXmlSimpleType(xst, values);
}
}
else if (xsCt != null)
{
XmlSchemaContentType xsContent = (XmlSchemaContentType) xsCt.ContentType;
XmlSchemaContentModel xsModel = (XmlSchemaContentModel)xsCt.ContentModel;
if (xsModel is XmlSchemaSimpleContent)
{
XmlSchemaSimpleContent xsSC = (XmlSchemaSimpleContent)xsModel;
XmlSchemaContent xsRE = xsSC.Content;
if (xsRE != null)
{
if (xsRE is XmlSchemaSimpleContentRestriction)
{
XmlSchemaSimpleContentRestriction xsCCR = (XmlSchemaSimpleContentRestriction)xsRE;
foreach (XmlSchemaObject xso in xsCCR.Facets)
{
if (xso is XmlSchemaEnumerationFacet)
{
XmlSchemaEnumerationFacet xsef = (XmlSchemaEnumerationFacet)xso;
values.Add(xsef.Value);
}
}
}
}
}
else
{
XmlSchemaComplexContent xsCC = (XmlSchemaComplexContent)xsModel;
XmlSchemaContent xsRE = xsCC.Content;
if (xsRE != null)
{
if (xsRE is XmlSchemaComplexContentRestriction)
{
XmlSchemaComplexContentRestriction xsR = (XmlSchemaComplexContentRestriction)xsRE;
}
else if (xsRE is XmlSchemaComplexContentExtension)
{
XmlSchemaComplexContentExtension xsE = (XmlSchemaComplexContentExtension)xsRE;
}
}
}
}
return values;
}
And to process a simple type:
private static void ProcessXmlSimpleType(XmlSchemaSimpleType xst, List<string> values)
{
if (xst == null)
{
return;
}
XmlSchemaSimpleTypeContent xsstc = xst.Content;
if (xsstc is XmlSchemaSimpleTypeRestriction)
{
XmlSchemaSimpleTypeRestriction xsr = (XmlSchemaSimpleTypeRestriction)xsstc;
XmlSchemaObjectCollection xsoc = xsr.Facets;
XmlSchemaSimpleType bastTypeOfRestiction = xsr.BaseType;
foreach (XmlSchemaObject xso in xsoc)
{
if (xso is XmlSchemaEnumerationFacet)
{
XmlSchemaEnumerationFacet xsef = (XmlSchemaEnumerationFacet)xso;
values.Add(xsef.Value);
}
}
}
else if (xsstc is XmlSchemaSimpleTypeList)
{
XmlSchemaSimpleTypeList xsstL = (XmlSchemaSimpleTypeList)xsstc;
XmlSchemaSimpleType xstL = xsstL.BaseItemType;
ProcessXmlSimpleType(xstL, values); // recursive
}
else if (xsstc is XmlSchemaSimpleTypeUnion)
{
XmlSchemaSimpleTypeUnion xstU = (XmlSchemaSimpleTypeUnion)xsstc;
XmlSchemaSimpleType[] xsstArray = xstU.BaseMemberTypes;
foreach (XmlSchemaSimpleType xsstA in xsstArray)
{
ProcessXmlSimpleType(xsstA, values); // recursive
}
}
}
The above code snippets probably address 20% of what's needed, but hopefully give you some idea of what you will be dealing with. .NET provides a very powerful set of classes for analysing the Schema Object Model, but you will need detailed knowledge of the XML Schema specification to get usable results.
XML editors should still provide auto-completion help when the XML is not valid, this adds an extra dimension to the problem because there may be ambiguities if there's limited validation context and the schema design is more 'russian-doll' than 'salami sliced'.
Summary
Getting a list of expected XML schema particles for a given context within an XML instance using .NET is possible but relatively complex. In view of this, it would be worthwhile to first check if libraries from existing .NET XML editors provide the functionality you need.
For a working implementation under LGPL have a look at SharpDevelops XmlEditor part.
You get the code completion for xml in one dll, namely the XmlEditor.dll in the AddIns/DisplayBindings directory.