Setting a default value when getting XML values via Linq - c#

I’m using Linq to extract values from some XML. Shown below is a simplified example to show the problem I’m having. The following code works fine on the XML shown below. The problem I have is when the groupBy section is missing. Because when it’s missing Data.Element("groupBy").Element("property) fails because Data.Element("groupBy") will be null. Is it possible to modify my Linq statement to allow it to provide a default or should it be approached in a different way?
var e = (from Data in theXML.Descendants("exportFile")
select new Export
{
OutputFileName = Data.Element("outputFileName") != null ? (string)Data.Element("outputFileName") : "",
GroupByProperty = Data.Element("groupBy").Element("property") != null ? (string)Data.Element("groupBy").Element("property") : ""
}).First();
<exportFile>
<outputFileName>output.xml</outputFileName>
<groupBy>
<property>DeviceId</property>
</groupBy>
</exportFile>

You can already make it slightly nicer than it is using the null coalescing operator. However, to cope with the groupby element being missing is harder:
select new Export
{
OutputFileName = (string) Data.Element("outputFileName") ?? "",
GroupByProperty = Data.Element("groupBy") == null ? ""
: (string) Data.Element("groupBy").Element("property") ?? ""
}).First();
The conversion to string just returns null if the element reference is null.
An alternative would be:
GroupByProperty =
(string) Data.Elements("groupBy").Elements("property").FirstOrDefault() ?? ""
That uses the extension method which allows you to call Elements on an IEnumerable<XElement>... so that will (lazily) evaluate a sequence of every property element under a groupBy element under Data, then take the first of them if any exist, then apply the string conversion.

You could simply add an additional check in the statement (and clean things up a bit using the null coalescing operator):
GroupByProperty = Data.Element("groupBy") != null ?
(Data.Element("groupBy").Element("property") ?? "") : "";

Related

Check if child object value exists NullReferenceException

I'm pretty new to C#. While attempting to set a local variable value, I'm running into a NullReferenceException.
It appears that the Buyer object is null, which I'm assuming is why it can't figure out the Buyer.Username value. What I'm not sure about is how to check if Buyer is not null AND that the Buyer.Username has a non-null value (in the most simple way possible). Unfortunately, I'm using C# 7.3 which doesn't appear to have support for the ?? operator.
BuyerUserName = string.IsNullOrEmpty(model.Transactions[i].Buyer.Username) ? "" : model.Transactions[i].Buyer.Username
Both ?? and ?. were introduced in C# 6, so you can use them:
BuyerUserName = model.Transactions[i].Buyer?.Username ?? string.Empty;
But even without that, there is nothing wrong with taking more than one line to do something, and you could just use an if statement:
var buyer = model.Transactions[i].Buyer;
if (buyer != null && buyer.Username != null)
BuyerUserName = buyer.Username;
else
BuyerUserName = string.Empty;

How to make the variable empty if the Jobject is empty in C#

I am getting a Null reference exception when the Jobject is empty.
var subjects = item.SelectToken("$.subjects").ToObject<List<JObject>>()
I am want to set var subjects as empty when Jobject empty without throwing an error.
THanks
var subjects = item.SelectToken("$.subjects")?.ToObject<List<JObject>>() ?? new List<JObject>();
List<...>
List is a collection and you need to define what's in the List. Like List<string>, List<object>, or, for your code, List<JObject>.
SelectToken("$.subjects")?.
This means that if SelectToken returns null, it stops there without doing .ToObject, and returns null.
The issue here is that SelectToken will return null when it can't find any object, and when you do .ToObject on a null you get a NullException. So one'd usually check if an object is null before further using its properties or functions.
The question mark - Null-Conditional Operator (Official documents) is a quick syntactic sugar to achieve that, without having to write conditions like
if (... == null)
{ ...convert to list... }
else
{ ...make empty list...}
?? new List()
Not sure what you mean by empty, if you don't want null, but an empty List, Null-coalescing Operator might come to help.
It means that if the statement before ?? is null, returns the statement after ?? instead.
For example, string a = b ?? c means:
string a = b != null ? b : c
But notice that a still can be null if c is null.
It's also a syntactic sugar to help you avoid writing long statements for these checks are frequently needed.

Handling null returns in new linq objects c#

What I'm going for? I need to post a newly created object to a db, the incoming object may have a null value. The created object is set to #nullible true where needed.
When data comes in and I land on a null string in my object I get a null reference and land on catch.
My code:
Objects.Data.Info.StoredData postData = new Objects.Data.Info.StoredData
{
Name = data.data.Name,
Type = data.data.Type,
Price = data.data.Price,
Indicator = data.data.Indicator,
Scan = data.data.Scan,
Comment = data.data.Extra
};
db.Information.Add(postData);
db.SaveChanges();
data.data.Extra can be null, sometimes.
I would usually write if statements to counter this, but don't feel like it's the best practice here. What direction should I go? I've checked a few other questions and msdn and can't find a clear path.
Thanks.
You can succinctly default to an empty string when the property is null by using the ?? operator, like so:
Comment = data.data.Extra ?? ""
//the value on the right is used if the expression on the left is null
?? is called the 'null-coalescing' operator: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator
If you also want to handle the intermediate properties being null (which I don't think applies to this case but is good to know), and still want to default to an empty string, you can combine this with Eugene's suggestion of using ?. like so:
Comment = data?.data?.Extra ?? ""
?. is called the 'null-conditional' operator: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/member-access-operators#null-conditional-operators--and-
var postData = new Objects.Data.Info.StoredData
{
Name = data.data.Name,
Type = data.data.Type,
Price = data.data?.Price,
Indicator = data.data.Indicator,
Scan = data.data.Scan,
Comment = data.data.Extra
};
db.Entry(postData).State=EntityState.Added;
db.SaveChanges();
I thought that you have facing difficulty with Price attribute because this one is Not null in your db once your programming cursor over there it failed, so once you exactly do what I did then eventually you change this nullable and then easily check or insert on runtime.
You should use the Null Conditional Operator (?.), like this:
data?.data?.Name
This will prevent an NullReferenceException if data or data.data is null.

Is there a less verbose and kludgy way to make otherwise-null SQL parameters safe?

I've got code for inserting a record into a SQL Server table which in some cases has some null values (if not replaced with pseudo-null (empty) vals first). Specifically, they are varchars.
If I don't check for null and assign string.empty in those instances:
if (null == _PatternOrdinal)
{
rs.PatternOrdinal = string.Empty;
}
else
{
rs.PatternOrdinal = _PatternOrdinal;
}
...it throws the exception, "The parameterized query '(#Unit varchar(25),#ReportID int,#NextExecution datetime,#NextEx' expects the parameter '#PatternOrdinal', which was not supplied."
IOW, if the code is simply this:
rs.PatternOrdinal = _PatternOrdinal;
...instead of the if block above, it crashes.
So I have to do that with several parameters. Is there a less verbose way to circumvent this periodic derailing?
You can use null-coalescing operator:
rs.PatternOrdinal = _PatternOrdinal ?? string.Empty;
It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.
But be aware that an empty string and a null value are not the same. An empty string is still a value, but a null means that there is no defined value.
In those cases where you need to save null values you should use DbNull.Value instead of an empty string.

Linq to sql: properties of properties that may be null

Simple LINQ query:
from transport in db.Transports
select new
{
Current = transport.CurrentLocation,
CurrentCarriers = transport.CurrentLocation.Carriers,
};
Problem: CurrentLocation may be null. If it is, executing this query throws a NullReference. I tried adding a check like
transport.CurrentLocation == null ? null : transport.CurrentLocation.Carriers
but Linq to sql does not seem to be able to parse that.
Any nice solutions that do not involve sending an extra query for each transport?
I normally just use 'let'.
from x in Foo
let y = x.Bar
where y != null
select y.Baz;
UPDATE:
I think the ?? operator does translate to SQL.
If the foreign key on Transports is nullable, you'll have to check that column for null before you can try and get the CurrentLocation object.
You could do something like this:
CurrentLocation = transport.currentLocationId != null ? transport.CurrentLocation : null;
Just do (you where using the wrong property):
transport.CurrentLocation == null ? null : transport.CurrentLocation.Carriers
Update 1: That is weird, I have used some pretty complex queries and didn't face that issue. I just checked one, don't think it matters, but mine had the check inverted:
transport.CurrentLocation != null ? transport.CurrentLocation.Carriers : null;
Can you post the complete query you tried that gives you the parse exception?

Categories