Need to get the sibling value - xpath

I need to create a cache using an XML file. Here's the method that I will be using. I want this method to return the id based on the key-product_name. So I want it to create a cache one time programmatically and then only if the key is not found then create a [new entry in the] cache. If everything looks okay the problem is getting the id of product. Please advise. I have included the code and xml file.
public static string getProductId(string product_name)
public static string getTechId(string fieldName)
{
Cache cache = HttpContext.Current.Cache; //neeed to change this.
string cacheNameEpm = product_name + "PrdName";
if (cache[cacheNameEpm] == null)
{
XPathDocument doc = new XPathDocument(HttpContext.Current.Request.MapPath("inc/xml/prd.xml"));
XPathNavigator navigator = doc.CreateNavigator();
string selectName = "/Products/Product/ProductName";
XPathNodeIterator nodes = navigator.Select(selectName);
while (nodes.MoveNext())
{
switch (nodes.Current.Name)
{
case "ProductName":
cacheNameEpm = nodes.Current.Value + "PrdName";
navigator.Select("/Products/Product/ProductId");
navigator.MoveToNext();
if (nodes.Current.Name == "ProductId")
{
id = navigator.Value;
}
cache.Add(cacheNameEpm, id, null, DateTime.Now + new TimeSpan(4, 0, 0), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Default, null);
break;
}
}
}
return cache[cacheNameEpm] as string;
}
Here is the xml file:
<Products>
<Product>
<ProductName>PDPArch</ProductName>
<ProductId>57947</ProductId>
</Product>
<Product>
<ProductName>TYFTType</ProductName>
<ProductId>94384</ProductId>
</Product>
</Products>

To get the product id of, say, "TYFTType", you would need this XPath expression:
/Products/Product[ProductName = 'TYFTType']/ProductId
So what about something along the lines of (untested, but you get the idea):
public static string getProductId(string product_name)
{
Cache cache = HttpContext.Current.Cache;
string cacheNameEpm = product_name + "PrdName";
if (cache[cacheNameEpm] == null)
{
// let's cache the navigator itself as well
string cacheNameNav = "prd.xml_Navigator";
XPathNavigator navigator = cache[cacheNameNav] as XPathNavigator;
if (navigator == null)
{
XPathDocument doc = new XPathDocument(
HttpContext.Current.Request.MapPath("inc/xml/prd.xml")
);
navigator = doc.CreateNavigator();
cache.Add(
cacheNameNav,
navigator,
null,
DateTime.Now + new TimeSpan(4, 0, 0),
Cache.NoSlidingExpiration,
CacheItemPriority.Default,
null
);
}
string xpath = String.Format(
"/Products/Product[ProductName = '{0}']/ProductId", product_name
);
XPathNavigator product_id = navigator.SelectSingleNode(xpath);
if (product_id.IsNode)
{
cache.Add(
cacheNameEpm,
product_id.Value,
null,
DateTime.Now + new TimeSpan(4, 0, 0),
Cache.NoSlidingExpiration,
CacheItemPriority.Default,
null
);
}
}
return cache[cacheNameEpm] as string;
}
The above has two little issues:
It will not remember the non-existent product names.
Product names must not contain a single quote or the XPath expression will break. You should add a check for this condition.

Related

Xamarin forms: Picture extension is not saving with path in android when do multiple photo selection

I am following this article for Select Multiple Images From Gallery in Xamarin Forms.
I completed the feature in android part but the picture path contains only the picture name, extensions are missing when saving path.
To upload the image to the server I need the complete image name with extension. So how can I save the complete path of the selected images with the extension?
Following method capture the image path:
public String GetRealPathFromURI(Android.Net.Uri contentURI)
{
try
{
ICursor imageCursor = null;
string fullPathToImage = "";
imageCursor = ContentResolver.Query(contentURI, null, null, null, null);
imageCursor.MoveToFirst();
int idx = imageCursor.GetColumnIndex(MediaStore.Images.ImageColumns.Data);
if (idx != -1)
{
fullPathToImage = imageCursor.GetString(idx);
}
else
{
ICursor cursor = null;
var docID = DocumentsContract.GetDocumentId(contentURI);
var id = docID.Split(':')[1];
var whereSelect = MediaStore.Images.ImageColumns.Id + "=?";
var projections = new string[] { MediaStore.Images.ImageColumns.Data };
cursor = ContentResolver.Query(MediaStore.Images.Media.InternalContentUri, projections, whereSelect, new string[] { id }, null);
if (cursor.Count == 0)
{
cursor = ContentResolver.Query(MediaStore.Images.Media.ExternalContentUri, projections, whereSelect, new string[] { id }, null);
}
var colData = cursor.GetColumnIndexOrThrow(MediaStore.Images.ImageColumns.Data);
cursor.MoveToFirst();
fullPathToImage = cursor.GetString(colData);
}
return fullPathToImage;
}
catch (Exception ex)
{
Toast.MakeText(Xamarin.Forms.Forms.Context, "Unable to get path", ToastLength.Long).Show();
}
return null;
}
The extension(.png or .jpg) was missing not from the GetRealPathFromURI(), it happens in ImageHelpers.SaveFile(). So I save the filename to another variable from the path using Path.GetFileName() like below and pass the complete filename when call ImageHelpers.SaveFile().
var fileName = Path.GetFileName(picturepath);

NetSuite / Suitescript - Why does this Validate Field script enter an infinite loop?

My script is entering into an infinite loop and I have no idea why. I am running this on validate field and I am preventing a change to the field if another vendor bill exists with the same reference number, forcing the user to change the "Reference Number" to be unique. Here is my code:
function validateField(type, name) {
if (uniqueReferenceNum(type, name) === false) {
return false;
}
return true;
}
function uniqueReferenceNum(type, name) {
if (name !== 'tranid') {
return true;
}
var tranID = nlapiGetFieldValue('tranid');
var vendor = nlapiGetFieldValue('entity');
var vendorName = nlapiGetFieldText('entity');
var filters = new Array();
var columns = new Array();
filters[0] = new nlobjSearchFilter('entity', null, 'is', vendor);
filters[1] = new nlobjSearchFilter('tranid', null, 'is', tranID);
filters[2] = new nlobjSearchFilter('mainline', null, 'is', 'T');
columns[0] = new nlobjSearchColumn('internalid');
results = nlapiSearchRecord('vendorbill', null, filters, columns);
if (!results) {
return true;
}
alert("There is already a vendor bill with reference # " + tranID + " for " + vendorName + ". Please verify and change the reference number before continuing.");
return false;
}
For those still facing this issue, you can set the field in question - in this case, Reference Number - to a 'falsy' value such as an empty string. Only return false after checking that the field contains a 'truthy' value. Then display the alert or dialog to the user. This should break the validation loop.

Comparing two lists with multiple conditions

I have two different lists of same type. I wanted to compare both lists and need to get the values which are not matched.
List of class:
public class pre
{
public int id {get; set;}
public datetime date {get; set;}
public int sID {get; set;}
}
Two lists :
List<pre> pre1 = new List<pre>();
List<pre> pre2 = new List<pre>();
Query which I wrote to get the unmatched values:
var preResult = pre1.where(p1 => !pre
.any(p2 => p2.id == p1.id && p2.date == p1.date && p2.sID == p1sID));
But the result is wrong here. I am getting all the values in pre1.
Here is solution :
class Program
{
static void Main(string[] args)
{
var pre1 = new List<pre>()
{
new pre {id = 1, date =DateTime.Now.Date, sID=1 },
new pre {id = 7, date = DateTime.Now.Date, sID = 2 },
new pre {id = 9, date = DateTime.Now.Date, sID = 3 },
new pre {id = 13, date = DateTime.Now.Date, sID = 4 },
// ... etc ...
};
var pre2 = new List<pre>()
{
new pre {id = 1, date =DateTime.Now.Date, sID=1 },
// ... etc ...
};
var preResult = pre1.Where(p1 => !pre2.Any(p2 => p2.id == p1.id && p2.date == p1.date && p2.sID == p1.sID)).ToList();
Console.ReadKey();
}
}
Note:Property date contain the date and the time part will be 00:00:00.
I fixed some typos and tested your code with sensible values, and your code would correctly select unmatched records. As prabhakaran S's answer mentions, perhaps your date values include time components that differ. You will need to check your data and decide how to proceed.
However, a better way to select unmatched records from one list compared against another would be to utilize a left join technique common to working with relational databases, which you can also do in Linq against in-memory collections. It will scale better as the sizes of your inputs grow.
var preResult = from p1 in pre1
join p2 in pre2
on new { p1.id, p1.date, p1.sID }
equals new { p2.id, p2.date, p2.sID } into grp
from item in grp.DefaultIfEmpty()
where item == null
select p1;

Building dynamic where clauses in LINQ to EF queries

I'm trying to build a where clause dynamically in a LINQ query which references tables via EF, but I'm getting the following error:
'ClaimantLastName' could not be resolved in the current scope or context. Make sure that all referenced variables are in scope, that required schemas are loaded, and that namespaces are referenced correctly. Near member access expression, line 6, column 2.
Here is what I'm trying:
string whereClause = string.Format("ClaimantLastName = '{0}' and ClaimantSSN = '{1}'", lastName, ssn);
I've also tried it without the single quotes to no avail.
Here is the actual query:
return db.Claims.Where(whereClause).Select(
u => new AdvancedSearchResult
{
ClaimNumber = u.ClaimNumber,
.
.
.
Is what I'm trying to do possible? It seems really basic. Where am I going wrong?
UPDATE: Here is the Claim entity.
public static Claim CreateClaim(global::System.Int32 id, global::System.String claimantFirstName, global::System.String claimantLastName, global::System.String claimantSSN, global::System.DateTime dateOfInjury, global::System.String claimNumber, global::System.String claimantMiddleName, global::System.String claimantAddress1, global::System.String claimantAddress2, global::System.String claimantCity, global::System.String claimantState, global::System.String claimantZip, global::System.DateTime claimantDateOfBirth, global::System.String compensability, global::System.Boolean injuryType, global::System.String jurisdictionState, global::System.String status, global::System.String condition, global::System.String managingBranch, global::System.String bodyPart, global::System.String acceptedBodyPart, global::System.Boolean pGCase, global::System.String employersDefenseAttorney, global::System.String accidentDescription, global::System.String claimExaminerFirstName, global::System.String claimExaminerLastName, global::System.String claimExaminerEmail, global::System.String claimantAttorney, global::System.String workerId, global::System.String workerType)
{
Claim claim = new Claim();
claim.Id = id;
claim.ClaimantFirstName = claimantFirstName;
claim.ClaimantLastName = claimantLastName;
claim.ClaimantSSN = claimantSSN;
claim.DateOfInjury = dateOfInjury;
claim.ClaimNumber = claimNumber;
claim.ClaimantMiddleName = claimantMiddleName;
claim.ClaimantAddress1 = claimantAddress1;
claim.ClaimantAddress2 = claimantAddress2;
claim.ClaimantCity = claimantCity;
claim.ClaimantState = claimantState;
claim.ClaimantZip = claimantZip;
claim.ClaimantDateOfBirth = claimantDateOfBirth;
claim.Compensability = compensability;
claim.InjuryType = injuryType;
claim.JurisdictionState = jurisdictionState;
claim.Status = status;
claim.Condition = condition;
claim.ManagingBranch = managingBranch;
claim.BodyPart = bodyPart;
claim.AcceptedBodyPart = acceptedBodyPart;
claim.PGCase = pGCase;
claim.EmployersDefenseAttorney = employersDefenseAttorney;
claim.AccidentDescription = accidentDescription;
claim.ClaimExaminerFirstName = claimExaminerFirstName;
claim.ClaimExaminerLastName = claimExaminerLastName;
claim.ClaimExaminerEmail = claimExaminerEmail;
claim.ClaimantAttorney = claimantAttorney;
claim.WorkerId = workerId;
claim.WorkerType = workerType;
return claim;
}
UPDATE: Added Paul's suggested code as a trial. This actually works.
whereClause = string.Format("ClaimantLastName = \"{0}\" and ClaimantSSN = \"{1}\"", lastName, ssn);
List<URIntake.Claim> claims = new List<Claim>();
URIntake.Claim claim = new Claim();
claim.ClaimantFirstName = "Jay";
claim.ClaimantLastName = "Williams";
claim.ClaimantSSN = "654219870";
claim.ClaimantDateOfBirth = new DateTime(1993, 1, 2);
claims.Add(claim);
claim = new Claim();
claim.ClaimantFirstName = "Santa";
claim.ClaimantLastName = "Claus";
claim.ClaimantSSN = "012345678";
claim.ClaimantDateOfBirth = new DateTime(1893, 1, 2);
claims.Add(claim);
List<AdvancedSearchResult> selectedClaims = claims.AsQueryable().Where(whereClause).Select(
u => new AdvancedSearchResult
{
ClaimNumber = u.ClaimNumber,
DateOfBirth = u.ClaimantDateOfBirth,
DateOfInjury = u.DateOfInjury,
Denied = u.Compensability == "Denied"
}).ToList();
Here's an example using System.Linq.Expressions. Although the example here is specific to your Claim class you can make functions like this generic and then use them to build predicates dynamically for all your entities. I've been using recently to provide users with a flexible search for entities on any entity property (or groups of properties) function without having to hard code all the queries.
public Expression<Func<Claim, Boolean>> GetClaimWherePredicate(
String name,
String ssn)
{
//the 'IN' parameter for expression ie claim=> condition
ParameterExpression pe = Expression.Parameter(typeof(Claim), "Claim");
//Expression for accessing last name property
Expression eLastName = Expression.Property(pe, "ClaimantLastName");
//Expression for accessing ssn property
Expression eSsn = Expression.Property(pe, "ClaimantSSN");
//the name constant to match
Expression cName = Expression.Constant(name);
//the ssn constant to match
Expression cSsn = Expression.Constant(ssn);
//the first expression: ClaimantLastName = ?
Expression e1 = Expression.Equal(eLastName, cName);
//the second expression: ClaimantSSN = ?
Expression e2 = Expression.Equal(eSsn, cSsn);
//combine them with and
Expression combined = Expression.And(e1, e2);
//create and return the predicate
return Expression.Lambda<Func<Claim, Boolean>>(
combined,
new ParameterExpression[] { pe });
}
I personally really like to use PredicateBuilder because it still has the LINQ look and feel, and not some magic string. You can have all sorts of conditions then add the clause to there predicate and it will compile all nice and clean for you.
http://www.albahari.com/nutshell/predicatebuilder.aspx
Here is a cut up sample from my own code:
var predicate = PredicateBuilder.True<MarketingCabinetItem>();
//add vendor filter
if (vendorComboBox.SelectedValue != null && !String.IsNullOrEmpty(vendorComboBox.SelectedValue.ToString()))
{
var vend = vendorComboBox.SelectedValue.ToString();
predicate = predicate.And(m => m.Vendor == vend);
vendPredicate.And(v => v.VendorName == vend);
}
//get all mkt item types in category
if (categoryComboBox.SelectedValue != null)
{
var mktCatId = Guid.Parse(categoryComboBox.SelectedValue.ToString());
predicate = predicate.And(p => p.CategoryCategoryId == mktCatId);
}
// get the marketing items using the inner and outer
var mktItems = (from mi in ctx.MarketingItem.AsExpandable()
join mType in ctx.ItemType.AsExpandable() on mi.MarketingItemTypeId equals mType.Id
join mktCat in ctx.Category.AsExpandable() on mType.MarketingItemCategoryId equals mktCat.Id
join att in ctx.Attachment.AsExpandable() on mi.Id equals att.MarketingItemId
join pri in ctx.Priority.AsExpandable() on mi.PriorityId equals pri.Id
select new MarketingCabinetItem
{
Id = mi.Id,
Title = mi.Title,
ItemTypeDescription = mType.Description,
PriorityLevel = pri.Level,
StartDate = mi.StartDate,
ExpirationDate = mi.ExpirationDate,
HasAttachments = att != null,
CategoryDescription = mktCat.Description
}).Where(predicate).ToList();
You could/need to use dynamic linq
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
db.Where("Something = #0 And SomethingElse = #1", "Blah", 42)
Seems to be how it is handled (note the lack of need for string.Format)
public class SearchField
{
public string Name { get; set; }
public string #Value { get; set; }
//public string Operator { get; set; }
public SearchField(string Name, string #Value)
{
this.Name = Name;
this.#Value = #Value;
//Operator = "=";
}
}
public class FilterLinq<T>
{
public static Expression<Func<T, Boolean>> GetWherePredicate(params SearchField[] SearchFieldList)
{
//the 'IN' parameter for expression ie T=> condition
ParameterExpression pe = Expression.Parameter(typeof(T), typeof(T).Name);
//combine them with and 1=1 Like no expression
Expression combined = null;
if (SearchFieldList != null)
{
foreach (var fieldItem in SearchFieldList)
{
//Expression for accessing Fields name property
Expression columnNameProperty = Expression.Property(pe, fieldItem.Name);
//the name constant to match
Expression columnValue = Expression.Constant(fieldItem.Value);
//the first expression: PatientantLastName = ?
Expression e1 = Expression.Equal(columnNameProperty, columnValue);
if (combined == null)
{
combined = e1;
}
else
{
combined = Expression.And(combined, e1);
}
}
}
//create and return the predicate
return Expression.Lambda<Func<T, Boolean>>(combined, new ParameterExpression[] { pe });
}
}
And You Can call it for any Class
ClinicEntities x = new ClinicEntities();
dataGridView1.DataSource = x.Patient
.Where(
FilterLinq<Patient>.GetWherePredicate(
new SearchField("PatientNameEnglish", "Mona Mohamed Ali"),
new SearchField("PatientHusbandName", "Ahmed Sallam Kareem"))).ToList();
Finally Thanks for bmused
the simple way is to use LINQExtension with LINQKIT
using (var context = new workEntities() )
{
Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
dictionary["Title"] = new List<string> {
"Network Engineer",
"Security Specialist",
"=Web Developer"
};
dictionary["Salary"] = new List<string> { ">=2000" };
dictionary["VacationHours"] = new List<string> { ">21" };
dictionary["SickLeaveHours"] = new List<string> { "<5" };
dictionary["HireDate"] = new List<string> {
">=01/01/2000",
"28/02/2014"
};
dictionary["ModifiedDate"] = new List<string> { DateTime.Now.ToString() };
var data = context.Employee.CollectionToQuery(dictionary).ToList();
}

EF single entity problem

I need to return a single instance of my viewmodel class from my repository in order to feed this into a strongly-typed view
In my repository, this works fine for a collection of viewmodel instances:
IEnumerable<PAWeb.Domain.Entities.Section> ISectionsRepository.GetSectionsByArea(int AreaId)
{
var _sections = from s in DataContext.Sections where s.AreaId == AreaId orderby s.Ordinal ascending select s;
return _sections.Select(x => new PAWeb.Domain.Entities.Section()
{
SectionId = x.SectionId,
Title = x.Title,
UrlTitle = x.UrlTitle,
NavTitle = x.NavTitle,
AreaId = x.AreaId,
Ordinal = x.Ordinal
}
);
}
But when I attempt to obtain a single entity, like this:
public PAWeb.Domain.Entities.Section GetSection(int SectionId)
{
var _section = from s in DataContext.Sections where s.SectionId == SectionId select s;
return _section.Select(x => new PAWeb.Domain.Entities.Section()
{
SectionId = x.SectionId,
Title = x.Title,
UrlTitle = x.UrlTitle,
NavTitle = x.NavTitle,
AreaId = x.AreaId,
Ordinal = x.Ordinal
}
);
}
I get
Error 1 Cannot implicitly convert type
'System.Linq.IQueryable<PAWeb.Domain.Entities.Section>' to
'PAWeb.Domain.Entities.Section'. An explicit conversion exists
(are you missing a cast?)"
This has got to be simple, but I'm new to c#, and I can't figure out the casting. I tried (PAWeb.Domain.Entities.Section) in various places, but no success. Can anyone help??
Your query is returning an IQueryable, which could have several items. For example, think of the difference between an Array or List of objects and a single object. It doesn't know how to convert the List to a single object, which one should it take? The first? The last?
You need to tell it specifically to only take one item.
e.g.
public PAWeb.Domain.Entities.Section GetSection(int SectionId)
{
var _section = from s in DataContext.Sections where s.SectionId == SectionId select s;
return _section.Select(x => new PAWeb.Domain.Entities.Section()
{
SectionId = x.SectionId,
Title = x.Title,
UrlTitle = x.UrlTitle,
NavTitle = x.NavTitle,
AreaId = x.AreaId,
Ordinal = x.Ordinal
}
).FirstOrDefault();
}
This will either return the first item, or null if there are no items that match your query. In your case that won't happen unless the table is empty since you don't have a where clause.

Resources