NullReferenceException while Reading XML File with Linq (C# 4.0) - visual-studio-2010

I'm completely stumped, I've used very similar code before and it worked perfectly, the XML in this was written by a separate method in this program and I checked it against it and it looked fine
That's the code for parsing the XML file
UserType CurrentUser = new UserType();
XDocument UserDoc = XDocument.Load(Path2UserFile);
XElement UserRoot = UserDoc.Element("User");
CurrentUser.User_ID = int.Parse(UserDoc.Element("User_ID").Value);
CurrentUser.Full_Name = UserDoc.Element("Full_Name").Value;
CurrentUser.Gender = UserDoc.Element("Gender").Value;
CurrentUser.BirthDate = DateTime.Parse(UserDoc.Element("Birthdate").Value);
CurrentUser.PersonType = int.Parse(UserDoc.Element("PersonType").Value);
CurrentUser.Username = UserDoc.Element("Username").Value;
CurrentUser.Password = UserDoc.Element("Password").Value;
CurrentUser.Email_Address = UserDoc.Element("Email_Address").Value;
The Path2UserFile points to the correct file as well, and I had it write out the full path.
It has a NullReferenceException whenever it tries to parse the contents of any of the elements
The XML File follows this format
<User>
<User_ID>11</User_ID>
<Full_Name>Sample User</Full_Name>
<Gender>Male</Gender>
<BirthDate>12/12/2010 12:00:00 AM</BirthDate>
<PersonType>2</PersonType>
<Username>Sample User</Username>
<Password>sample123</Password>
<Email_adddress>sampleuser#gmail.com</Email_adddress>
</User>
The UserType class looks like this
class UserType
{
public int User_ID = 0;
public string Full_Name = string.Empty;
public string Gender = string.Empty;
public DateTime BirthDate;
public int PersonType = 0;
public string Username = string.Empty;
public string Password = string.Empty;
public string Email_Address = string.Empty;
}
I have no clue as to what's wrong, any help would be very much appreciated

Change all the UserDoc references to UserRoot (the ones after the UserRoot declaration). Since the object is an XDocument rather than an XElement you need to operate at that level. Otherwise you can refer to UserDoc.Root.Element(...) instead but that's lengthier.
UserType CurrentUser = new UserType();
XDocument UserDoc = XDocument.Load(Path2UserFile);
XElement UserRoot = UserDoc.Root;
CurrentUser.User_ID = int.Parse(UserRoot.Element("User_ID").Value);
CurrentUser.Full_Name = UserRoot.Element("Full_Name").Value;
CurrentUser.Gender = UserRoot.Element("Gender").Value;
CurrentUser.BirthDate = DateTime.Parse(UserRoot.Element("BirthDate").Value);
CurrentUser.PersonType = int.Parse(UserRoot.Element("PersonType").Value);
CurrentUser.Username = UserRoot.Element("Username").Value;
CurrentUser.Password = UserRoot.Element("Password").Value;
CurrentUser.Email_Address = UserRoot.Element("Email_address").Value;
Also, be aware of your case. Use BirthDate instead of Birthdate (capital "D" to match your XML). Similarly, it's Email_address not Email_Address (lowercase "a") and your XML has 3 D's in "address" (spelling mistake).

Related

How to get a recordid from OrientDB on insert?

OrientDB question...
Does anyone know how I can get the recordId after an insert:
db.save(person)
I tried below on the Person POJO:
#Id
private Object id;
but the id field was null after the save. I've googled and googled to no avail. I just need to insert an object, then get the recordid that orientdb generates.
Define field in pojo:
#Id
private Object rid;
public Object getRid() {
return rid;
}
When save:
YourClass proxy = db.save(yourClassInstance);
Object rid = proxy.getRid();
I got it to work using ODocuments instead of POJOs (which works for my project). Code sample:
ODatabaseDocumentTx db = null;
ODocument doc = null;
db = new ODatabaseDocumentTx("local:" + System.getProperty("user.home") + "/testDB");
db.create();
doc = new ODocument("Person");
doc.field("name", "Peter");
doc.save();
String rid = doc.getIdentity().toString();
List<ODocument> results = db.query(new OSQLSynchQuery<ODocument>("select from " + rid));
for (ODocument aDoc : results) {
System.out.println(aDoc.field("name"));
}
db.close();
It's just simple here is the code:
//insertquery will be the sql statement you want to insert
ODocument result=db.command(new OCommandSQL(insertquery)).execute();
System.out.println(result.field("#rid"));
Alternatively you can make use of getRecordByUserObject() of OObjectDatabaseTx,
OObjectDatabaseTx db = new OObjectDatabaseTx("local:" + System.getProperty("user.home") + "/testDB");
ODocument oDocument = db.getRecordByUserObject( person, true );
oDocument.save();
String rid = oDocument.getIdentity().toString();
If you already have access to your proxy object from the save, you can totally do a cool cast on it to get the underlying ODocument object which has a record ID (Identity).
Person proxyPerson = db.save(person);
ODocument oDocument = ((OObjectProxyMethodHandler)((ProxyObject)proxyPerson).getHandler()).getDoc();
person.setId(oDocument.getIdentity().toString());

Save Entity Framework Linq Query to database

I was wondering if we can convert a Linq Query on the Entity Framework and save the query to the database by converting it to an Expression Tree and Serializing. Can someone please help me on this and point me in a right direction whether this can be done or not. Any help is greatly appreciated on this.
Thanks,
Ajay.
i released a library for that purpose just yesterday. Serialize.Linq. It serializes linq expressions to xml, json or binary.
using System.Linq.Expressions
using Serialize.Linq.Extensions;
Expression<Func<Person, bool>> query = p => p.LastName == "Miller"
&& p.FirstName.StartsWith("M");
Console.WriteLine(query.ToJson());
Console.WriteLine(query.ToXml());
You could turn the query into a string and then save the string.
This is from an answer by Nick Berardi:
var result = from x in appEntities
where x.id = 32
select x;
var sql = ((System.Data.Objects.ObjectQuery)result).ToTraceString();
The sql generated by the query could be stored and re-used.
Use Sprint.Filter.OData. It converts a Func<T,bool> into string and back to code.
Sample:
public class TestSprintOData
{
public static void Run()
{
// Parse a Func into string
var query = Filter.Serialize<User>(u => u.IsActive && u.Email.Contains("#gmail.com"));
// It'll generate the string "IsActive and substringof('#gmail.com', Email)"
// Convert back to Expression, perhaps on server
var query2 = Filter.Deserialize<User>(query);
// Compiles to Func, so you can use as delegate to Where
var f = query2.Compile();
var list = new List<User>
{
new User{Name="Johnny", IsActive = true, Email = "johnny#gmail.com"},
new User{Name="abc", IsActive = false, Email = ""},
new User{Name="dude", IsActive=true, Email = "dude#gmail.com"}
};
var result = list.Where(f);
}
}
class User
{
public string Name;
public string Phone;
public string Login;
public string Email;
public bool IsActive;
}
You can also use it as a Nuget Package
You may want to consider using Entity SQL rather than LINQ in this case. Entity SQL is a string query that works against your EF conceptual model rather than directly against the database.

How to use a string in the linq where clause?

I am trying to send a Linq query as a string to a method to be used in a where clause. Since IEnumerable wouldn't work for this, I have converted my IEnumerable to IQueryable and still it throws error. The following is the code:
public static void FilterData(string Query)
{
if((List<MemberMaintenanceData>)HttpContext.Current.Session["Allmembers"] != null)
{
//Get the IEnumerable object colection from session
var data = (List<MemberMaintenanceData>) HttpContext.Current.Session["Allmembers"];
//Convert it to IQueryable
IQueryable<MemberMaintenanceData> queryData = data.AsQueryable();
//This line doesn't compile!!
queryData = queryData.Where(Query);
HttpContext.Current.Session["Allmembers"] = queryData.AsEnumerable().ToList();
}
}
I intended passing "a => a.AccountId == 1000" as Query
There is a free (and open source) library, provided by Microsoft for parsing strings into Lambda expressions that can then be used in Linq queries. It also contains versions of the standard query operators such as Where() that take a string parameter. You can find it described in Scott Guthries blog post on Dynamic Linq.
For example, you can do queries like this (adapted from a snippet from the Scott guthrie link)
// imagine these have come from a drop down box or some other user input...
string thingToSelectBy = "City";
string citySelectedByUser = "London";
int minNumberOfOrders = 10;
string whereClause = String.Format("{0} = #0 and Orders.Count >= #1", thingToSelectBy);
var query = db.Customers
.Where(whereClause, citySelectedByUser, minNumberOfOrders)
.OrderBy("CompanyName")
.Select("new(CompanyName as Name, Phone");
The Where clause in thisw code snippet shows how you create a where clause using a parameterised string and then dynamically inject values for the parameters at run time, for example, based on user input. This works for parameters of any type.
In your example, the where clause would be
whereClause = "AccountId = 1000";
So in effect you would be doing something like
var newFilteredQueryData = queryData.Where("AccountId = 1000");
That link also contains the location where you can download the source code and a comprehensive document describing the dynamic query API and expression language.
Given a class such as:
public class foo
{
public int AccountID {get;set;}
}
You should be able to do something like this:
Expression<Func<foo, bool>> filter = f => f.AccountID == 1000;
And then pass that as your query. If it is really needed as a string you can do this:
filter.ToString();
//By Using this library
using System.Linq.Dynamic.Core;
InventoryList = Repository.GetAll(); // IQueryable
string filterString = "UnitPrice > 10 And Qty>100 OR Description.Contains("Dairy")";
var filteredGenericList = InventoryList.Where(filterString);

How to set the default namespace or how to define the #key values when using google-api and using Atom serialization/parser

I'm having trouble with Atom parsing/serializing - clearly something related to the namespace and the default alias - but I can;t figure out what I'm doing wrong.
I have two methods - one that I'm trying to do a GET and see if an album is defined and what that tries to do a POST to create the album (if it does not exist).
The GET I managed to get working - although there too I'm pretty sure I am doing something wrong because it is different from the PicasaAndroidSample. Specifically, if I define:
public class EDAlbum {
#Key("atom:title")
public String title;
#Key("atom:summary")
public String summary;
#Key("atom:gphoto:access")
public String access;
#Key("atom:category")
public EDCategory category = EDCategory.newKind("album");
}
Then the following code does indeed get all the albums:
PicasaUrl url = PicasaUrl.relativeToRoot("feed/api/user/default");
HttpRequest request = EDApplication.getRequest(url);
HttpResponse res = request.execute();
EDAlbumFeed feed = res.parseAs(EDAlbumFeed.class);
boolean hasEDAlbum = false;
for (EDAlbum album : feed.items) {
if (album.title.equals(EDApplication.ED_ALBUM_NAME)) {
hasEDAlbum = true;
break;
}
}
But - if instead I have:
public class EDAlbum {
#Key("title")
public String title;
#Key("summary")
public String summary;
#Key("gphoto:access")
public String access;
#Key("category")
public EDCategory category = EDCategory.newKind("album");
}
Then the feed has an empty collection - i.e. the parser does not know that this is Atom (my guess).
I can live with the android:title in my classes - I don;t get it, but it works.
The problem is that I can't get the POST to wok (to create the album). This code is:
EDAlbum a = new EDAlbum();
a.access = "public";
a.title = EDApplication.ED_ALBUM_NAME;
a.summary = c.getString(R.string.ed_album_summary);
AtomContent content = new AtomContent();
content.entry = a;
content.namespaceDictionary = EDApplication.getNamespaceDictionary();
PicasaUrl url = PicasaUrl.relativeToRoot("feed/api/user/default");
HttpRequest request = EDApplication.postRequest(url, content);
HttpResponse res = request.execute();
The transport and namespace are:
private static final HttpTransport transport = new ApacheHttpTransport(); // my libraries don;t include GoogleTransport.
private static HttpRequestFactory createRequestFactory(final HttpTransport transport) {
return transport.createRequestFactory(new HttpRequestInitializer() {
public void initialize(HttpRequest request) {
AtomParser parser = new AtomParser();
parser.namespaceDictionary = getNamespaceDictionary();
request.addParser(parser);
}
});
}
public static XmlNamespaceDictionary getNamespaceDictionary() {
if (nsDictionary == null) {
nsDictionary = new XmlNamespaceDictionary();
nsDictionary.set("", "http://www.w3.org/2005/Atom");
nsDictionary.set("atom", "http://www.w3.org/2005/Atom");
nsDictionary.set("exif", "http://schemas.google.com/photos/exif/2007");
nsDictionary.set("gd", "http://schemas.google.com/g/2005");
nsDictionary.set("geo", "http://www.w3.org/2003/01/geo/wgs84_pos#");
nsDictionary.set("georss", "http://www.georss.org/georss");
nsDictionary.set("gml", "http://www.opengis.net/gml");
nsDictionary.set("gphoto", "http://schemas.google.com/photos/2007");
nsDictionary.set("media", "http://search.yahoo.com/mrss/");
nsDictionary.set("openSearch", "http://a9.com/-/spec/opensearch/1.1/");
nsDictionary.set("xml", "http://www.w3.org/XML/1998/namespace");
}
return nsDictionary;
}
If I use
#Key("title")
public String title;
then I get an exception that it does not have a default namespace:
W/System.err( 1957): java.lang.IllegalArgumentException: unrecognized alias: (default)
W/System.err( 1957): at com.google.common.base.Preconditions.checkArgument(Preconditions.java:115)
W/System.err( 1957): at com.google.api.client.xml.XmlNamespaceDictionary.getNamespaceUriForAliasHandlingUnknown(XmlNamespaceDictionary.java:288)
W/System.err( 1957): at com.google.api.client.xml.XmlNamespaceDictionary.startDoc(XmlNamespaceDictionary.java:224)
and if I use
#Key("atom:title")
public String title;
then it does serialize but each element has the atom: prefix and the call fails - when I to a tcpdump on it I see something like
.`....<? xml vers
ion='1.0 ' encodi
ng='UTF- 8' ?><at
om:entry xmlns:a
tom="htt p://www.
w3.org/2 005/Atom
"><atom: category
scheme= "http://
schemas. google.c
om/g/200 5#kind"
term="ht tp://sch
emas.goo gle.com/
photos/2 007#albu
m" /><at om:gphot
o:access >public<
/atom:gp hoto:acc
....
What do I need to do different in order to use
#Key("title")
public String title;
and have both the GET and the POST manage the namespace?
It looks you are adding either duplicate dictonary keys or keys that are not understood by the serializer.
Use the following instead.
static final XmlNamespaceDictionary DICTIONARY = new XmlNamespaceDictionary()
.set("", "http://www.w3.org/2005/Atom")
.set("activity", "http://activitystrea.ms/spec/1.0/")
.set("georss", "http://www.georss.org/georss")
.set("media", "http://search.yahoo.com/mrss/")
.set("thr", "http://purl.org/syndication/thread/1.0");
Removing the explicit set for the "atom" item namespace solved this issue for me.

Object initialization syntax

I'm just starting out with F# and I can't find the syntax to do object initialization like in C# 3.
I.e. given this:
public class Person {
public DateTime BirthDate { get; set; }
public string Name { get; set; }
}
how do I write the following in F#:
var p = new Person { Name = "John", BirthDate = DateTime.Now };
You can do it like this:
let p = new Person (Name = "John", BirthDate = DateTime.Now)
the answer from CMS is definitely correct. Here is just one addition that may be also helpful. In F#, you often want to write the type just using immutable properties. When using the "object initializer" syntax, the properties have to be mutable. An alternative in F# is to use named arguments, which gives you a similar syntax, but keeps things immutable:
type Person(name:string, ?birthDate) =
member x.Name = name
member x.BirthDate = defaultArg birthDate System.DateTime.MinValue
Now we can write:
let p1 = new Person(name="John", birthDate=DateTime.Now)
let p2 = new Person(name="John")
The code requires you to specify the name, but birthday is an optional argument with some default value.
You can also omit the new keyword and use less verbose syntax:
let p = Person(BirthDate = DateTime.Now, Name = "John")
https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/members/constructors

Resources