How to allow null in Context.Request:
context.Response.Write(retrieveList(context.Request["SalCode"].ToString(null), context.Request["groupKeyword"].ToString(), context.Request["text"].ToString()));
Firstly, Request["..."] already returns a string, so there is no need to call ToString() on it and thus no need to worry, at this stage, if it returns null (i.e. if the key is not present in the request).
Thus you can call e.g.
retrieveList(
context.Request["SalCode"],
context.Request["groupKeyword"],
context.Request["text"]);
without worrying if any of the three are null.
You can then alter retrieveList to respond correctly if any of the inputs is null. For example, you could return null:
private string /*or whatever*/ retrieveList(
string salCode, string groupKeyword, string text)
{
if (String.IsNullOrEmpty(salCode) ||
String.IsNullOrEmpty(groupKeyword) ||
String.IsNullOrEmpty(text))
{
return null;
}
...
}
Then, note that Response.Write doesn't care if you give it a null, it just writes nothing, so you can keep the call to Write as above.
Alternatively, you could for example check the return value and write a message if it is null:
var list = retrieveList(
context.Request["SalCode"],
context.Request["groupKeyword"],
context.Request["text"]));
if (!String.IsNullOrEmpty(list))
{
context.Response.Write(list);
}
else
{
context.Response.Write("Missing request parameter.");
}
TYou didn't specify anything! Please add information, you even didn't specify the environment, the classes, or the general context in which this problem occurs. nor do we know what the signature of retrieveList() is! This makes us very difficult to help you! How much would you like to answer the question, one of my colleagues faced once: 'This crap doesn't work!' ? (Yes, it is not even a question, but happened in a real life support situatiuon!)
One thing I noted is that you use *T*oString() instead of *t*oString(), I assume that is a typo. (edited, as it is clear that this is C#) Also, I don't know what .toString(null) means. Did you want to tell us that that statement causes the NullPointerException? In that case, you could have committed a bit more effort towards us to understand your question, e.g. by writing this down...
BTW, if that's the case, I'd say, this will solve your problem:
Object salCode = context.Request["SalCode"];
context.Response.Write(retrieveList(salCode==null?"":salCode.ToString(), context.Request["groupKeyword"].ToString(), context.Request["text"].ToString()));
EDIT I think (but have no means to test) that if the null is the problem, this would fix it. If however, the underlying code does not work properly with empty String specified, that should be checked in retrieveList() like this (pasted from referenced post):
private string retrieveList(string SalCode, string groupKeyword, string text)
{
SqlConnection _sqlCon = default(SqlConnection);
SqlCommand _sqlCom = default(SqlCommand);
SqlDataReader _sqlReader = default(SqlDataReader);
StringBuilder _sb = new StringBuilder();
List<TokenInputJSON> _out = null;
try
{
_sqlCon = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["SalesianBlastConnectionString"].ConnectionString);
_sqlCom = new SqlCommand("getTokenInput", _sqlCon);
_sqlCom.CommandType = CommandType.StoredProcedure;
_sqlCon.Open();
//This is the edited part
if(SalCode==null || SalCode.Equals("")) {
_sqlCom.Parameters.Add(new SqlParameter("#salCode", SqlDbType.VarChar, 4)).Value = SalCode;
}
//... continue with the other parts
Quick check: I just had an idea: use a constant value when calling retrieveList to find out if this is the problem:
context.Response.Write(retrieveList("enterAValidSalCodeHere", context.Request["groupKeyword"].ToString(), context.Request["text"].ToString()));
Related
i'm building an url using flurl.
This is an example of what i am doing:
var res = baseUrl.AppendPathSegment(a).SetQueryParam(b);
I would like to make flurl skip adding "a" or "b" when they are string.empty. Is that possible?
At the moment i see that flurl is adding "a" and "b" to the url even if they are empty.
Thank you
Let's test a few scenarios:
"http://example.com/".AppendPathSegment("").AppendPathSegment("")
Result: http://example.com/, which (if I understand you correctly) is exactly what you want. But, AppendPathSegment will throw an exception if you pass null, so I would suggest this in your case:
baseUrl.AppandPathSegment(a ?? "")
Next up:
"http://example.com/".AppendPathSegment("").SetQueryParam("x", null)
Also leaves you with http://example.com/. But an empty string value (instead of null) will append ?x=, so you may need to replace any empty string with null in this case.
However, it looks like you're using the less-common overload of AppendQueryParam that takes a single argument.
"http://example.com/".SetQueryParam("")
"http://example.com/".SetQueryParam(null)
In both cases the result is http://example.com/?. The server shouldn't behave differently in this case than it would without the ?, but if you're finding that's not true in your case, then Flurl doesn't have a built-in way to deal with it. You'll need to either avoid it with an if statement or use TrimEnd('?') on the string result.
If you don't want to use the path segment or query param because the parameter a or b is empty or null use an if statement:
var res = baseUrl;
if(!string.IsNullOrWhiteSpace(a))
{
res = res.AppendPathSegment(a);
}
if(!string.IsNullOrWhiteSpace(b))
{
res = res.SetQueryParam(b);
}
,Hi
List<Claimant> list = (from c in CacheManager.ClaimantList.List
where
c.Fullname.Replace("i", "İ").Replace("ı","I").ToUpper().Contains(searchKey.Replace("i", "İ").Replace("ı", "I").ToUpper())
|| c.IdentityNumber.Replace("i", "İ").Replace("ı", "I").ToUpper().Contains(searchKey.Replace("i", "İ").Replace("ı", "I").ToUpper())
|| c.TaxNumber.Replace("i", "İ").Replace("ı", "I").ToUpper().Contains(searchKey.Replace("i", "İ").Replace("ı", "I").ToUpper())
select c).Take(20).ToList<Claimant>();
If Taxnumber is null or "" i get exception because of null data.
My question:
How can i set Taxnumber == 0 , if Taxnumber is null or "" ?
Any help will be appreciated.
Thanks.
You can do:
from c in CacheManager.ClaimantList.List
let taxNumber = c.TaxNumber == null || c.TaxNumber == "" ? "0" : c.TaxNumber
where ...
and then use the taxNumber variable rather than the column.
If you just want certain columns and you don't need the whole Claimant object, you can put something into a select
from c in ClaimantList
where (...)
select new {c.FullName, c.IdentityNumber, TaxNumber = String.IsNullOrEmpty(c.TaxNumber) ? "0" : c.TaxNumber}
You now have an anonymous type with three fields: original FullName, original IdentityNumber and modified TaxNumber.
You could also create a new Claimant for each value by calling its constructor each time:
from c in ClaimantList
where (...)
select new Claimant() {FullName = c.FullName, IdentityNumber = c.IdentityNumber, TaxNumber = String.IsNullOrEmpty(c.TaxNumber) ? "0" : c.TaxNumber}
(I don't know what the constructor of Claimant is like, you might do this slightly differently and set those values in the constructor rather than in the initializer. Or you could write a new constructor.) If the constructor does something non-trivial, it might be wasteful of resources to call it this many times.
In either case, it is stylistically nice to put the conversion (String.IsNullOrEmpty(TaxNumber) ? "0" : TaxNumber or whatever) into its own function somewhere, so that you can change what conversion you do later (see below), and don't have to repeat the code in multiple places.
Another option is that you could use the objects you have, but change the TaxNumber as required. LINQ isn't really the best way of doing this, as you are basically applying side-effects. (LINQ likes to supply a new container with the right data in it, rather than change the data in the original container.) You should really run foreach outside of the Linq code, like this:
List<Claimant> list = from ...
where ...
select ...
foreach (Claimant claimant in list)
{
if (String.IsNullOrEmpty(claimant.TaxNumber))
{ claimant.TaxNumber = "0"; }
}
Ideally you do this after the Take(20) so that you only do it the number of times you need.
Again, putting the conversion in a function will be neater and nicer:
List<Claimant> list = from ...
where ...
select ...
foreach (Claimant claimant in list)
{
claimant.TaxNumber = NormalizeTaxNumber(claimant.TaxNumber); }
}
// ...
public static string NormalizeTaxNumber(string n)
{
return String.IsNullOrEmpty(n) ? "0" : n;
}
However, if you have gone down this route, the next option is to add a method to Claimant which does this change:
List<Claimant> list = from ...
where ...
select ...
foreach (Claimant claimant in list)
{
claimant.NormalizeTaxNumber();
}
public class Claimant
{
// ...
public void NormalizeTaxNumber()
{
if (String.IsNullOrEmpty(TaxNumber))
{ TaxNumber = "0"; }
}
}
and to call this from the foreach loop.
Or, use a different property than TaxNumber:
public class Claimant
{
// ...
public string NormalTaxNumber
{
get { return String.IsNullOrEmpty(TaxNumber) ? "0" : TaxNumber; }
}
}
The advantage of the first strategy is that you only have to call it once - the advantages of the second are that it keeps the original value still available (in the TaxNumber property), and that if you have a bunch of Claimant objects, you don't have to remember whether you have normalized them or not.
You could also use a combination of the two methods: add a new property NormalTaxNumber which converts TaxNumber when needed, and which caches the result so that conversion doesn't have to be done again.
public class Claimant
{
// ...
private string m_normalTaxNumber;
private string ConvertedTaxNumber
{
get { return String.IsNullOrEmpty(TaxNumber) ? "0" : TaxNumber; }
}
public string NormalTaxNumber
{
get
{
if (m_normalTaxNumber == null)
{ m_normalTaxNumber = ConvertedTaxNumber; }
return m_normalTaxNumber;
}
}
}
This only does the calculation once, keeps the original still available, and doesn't require to remember if you've called it before or not. If TaxNumber (the original value) isn't readonly, this is probably more trouble than it's worth as you will have to invalidate the cached value.
If you are never, never going to need to know whether the TaxNumber was originally null, empty or "0", the best advice (and the last strategy) is to convert to the form you want as soon as possible, preferably in the Claimant constructor, if the value of TaxNumber is known there.
If you are getting Claimant objects from a database, you could take this to its logical limit by doing the conversion on the database, either in a stored proc or in a view. If you are using LinqToSql to get the list of Claimant objects, a view could work for you but a stored proc might not.
I have assumed throughout that you want TaxNumber to be available as a string, and that by 0 you mean the string "0". If this isn't the case, and you actually want convert to an int (or similar), some of the strategies above will still work. You can select the converted value as an int in an anonymous type, you can make a new property NormalTaxNumber (with int type), whether cached or not cached, or you can do the conversion upon creation of a Claimant object. Obviously you can't overwrite the string TaxNumber with an int.
If you are parsing the string to an int, things like NormalTaxNumber with caching become more worthwhile, because the conversion from string to int is more costly. (Checking for null or "" is actually very fast, however I thought it valuable to go through some different options anyway.)
Note that almost all of these should still be available to you if you can't modify the Claimant class. You can't write a new constructor, but you can write a factory method which encapsulates exactly the same behavior as a constructor. You can add NormalizeTaxNumber as an extension method, and while you can't add properties, you can add extension methods with no arguments which work almost exactly like properties.
My last observation is that "0" might not necessarily be a better value for missing data than null or "". Either of the latter is more commonly used to indicate missing values, especially null. Perhaps you should choose one of those as the default (and maybe apply one of the above strategies in reverse to enforce it as the only 'N/A' value?) If it's just a question of it looking nice when you print the object out, you could override ToString() to swap in the "0" only when needed.
I spend a lot of time querying a database and then building collections of objects from the query. For performance I tend to use a Datareader and the code looks something like:
while(rdr.Read()){
var myObj = new myObj();
myObj.Id = Int32.Parse(rdr["Id"].ToString();
//more populating of myObj from rdr
myObj.Created = (DateTime)rdr["Created"];
}
For objects like DateTime I simply cast the rdr value to the required class, but this can't be done for value types like int hence the (IMHO) laborious ToString() followed by Int.Parse(...)
Of course there is an alternative:
myObj.Id = rdr.GetInt32(rdr.GetOrdinal("Id"));
which looks cleaner and doesn't involve a call to ToString().
A colleague and I were discussing this today - he suggests that accessing rdr twice in the above code might be less efficient that doing it my old skool way - could anyone confirm or deny this and suggest which of the above is the best way of doing this sort of thing? I would especially welcome answers from #JonSkeet ;-)
I doubt there will be a very appreciable performance difference, but you can avoid the name lookup on every row simply by lifting it out of the loop. This is probably the best you'll be able to achieve:
int idIdx = rdr.GetOrdinal("Id");
int createdIdx = rdr.GetOrdinal("Created");
while(rdr.Read())
{
var myObj = new myObj();
myObj.Id = rdr.GetFieldValue<int>(idIdx);
//more populating of myObj from rdr
myObj.Created = rdr.GetFieldValue<DateTime>(createdIdx);
}
I usually introduce a RecordSet class for this purpose:
public class MyObjRecordSet
{
private readonly IDataReader InnerDataReader;
private readonly int OrdinalId;
private readonly int OrdinalCreated;
public MyObjRecordSet(IDataReader dataReader)
{
this.InnerDataReader = dataReader;
this.OrdinalId = dataReader.GetOrdinal("Id");
this.OrdinalCreated = dataReader.GetOrdinal("Created");
}
public int Id
{
get
{
return this.InnerDataReader.GetInt32(this.OrdinalId);
}
}
public DateTime Created
{
get
{
return this.InnerDataReader.GetDateTime(this.OrdinalCreated);
}
}
public MyObj ToObject()
{
return new MyObj
{
Id = this.Id,
Created = this.Created
};
}
public static IEnumerable<MyObj> ReadAll(IDataReader dataReader)
{
MyObjRecordSet recordSet = new MyObjRecordSet(dataReader);
while (dataReader.Read())
{
yield return recordSet.ToObject();
}
}
}
Usage example:
List<MyObj> myObjects = MyObjRecordSet.ReadAll(rdr).ToList();
This makes the most sense to a reader. Whether it's the most "efficient" (you're literally calling two functions instead of one, it's not going to be as significant as casting, then calling a function). Ideally you should go with the option that looks more readable if it doesn't hurt your performance.
var ordinal = rdr.GetOrdinal("Id");
var id = rdr.GetInt32(ordinal);
myObj.Id = id;
Actually there is are differences in performance in how you use SqlDataReader, but they are somewhere else. Namely the ExecuteReader method accepts the CommandBehavior.SequentialAccess:
Provides a way for the DataReader to handle rows that contain columns with large binary values. Rather than loading the entire row, SequentialAccess enables the DataReader to load data as a stream. You can then use the GetBytes or GetChars method to specify a byte location to start the read operation, and a limited buffer size for the data being returned.
When you specify SequentialAccess, you are required to read from the columns in the order they are returned, although you are not required to read each column. Once you have read past a location in the returned stream of data, data at or before that location can no longer be read from the DataReader. When using the OleDbDataReader, you can reread the current column value until reading past it. When using the SqlDataReader, you can read a column value only once.
If you do not use large binary values then it makes very little difference. Getting a string and parsing is suboptimal, true, is better to get the value with rdr.SqlInt32(column) rather than a GetInt32() because of NULL. But the difference should not be noticeable on most application, unles your app is trully doing nothing else but read huge datasets. Most apps do not behave that way. Focusing on optimising the databse call itself(ie. have the query execute fast) will reap far greater benefits 99.9999% of the times.
For objects like DateTime I simply cast the rdr value to the required class, but this can't be done for value types like int
This isn't true: DateTime is also a value type and both of the following work in the same way, provided the field is of the expected type and is not null:
myObj.Id = (int) rdr["Id"];
myObj.Created = (DateTime)rdr["Created"];
If it's not working for you, perhaps the field you're reading is NULL? Or not of the required type, in which case you need to cast twice. E.g. for a SQL NUMERIC field, you might need:
myObj.Id = (int) (decimal) rdr["Id"];
I have a class where one of the property return a List<object>. Inside that list I put a set of anonymous objects.
Then later of, I have a loop using that property's item as dynamic variable.
So my code looks like this:
private List<object> BookerTypes
{
get
{
if (this.bookerTypes == null)
{
this.bookerTypes = new List<object>();
var com = new SqlConnection(functions.ConnectionString).CreateCommand();
com.CommandText = #"
SELECT
BT.id
, BT.name
FROM dbo.BookerTypes AS BT
ORDER BY BT.name ASC
";
com.Connection.Open();
try
{
using (var dr = com.ExecuteReader())
{
while (dr.Read())
{
this.bookerTypes.Add(new { id = dr.GetInt32(0), name = dr.GetString(1) });
}
}
}
finally
{
com.Connection.Close();
}
}
return this.bookerTypes;
}
}
[...]
this.cblSBT.Items.Clear();
foreach(dynamic bt in this.BookerTypes)
{
this.cblSBT.Items.Add(new ListItem()
{
Value = bt.id.ToString()
, Text = bt.name
, Selected = this.competition.SubscriptionTypes.Contains((int)bt.id)
});
}
Aside from the obvious lost of strongly typed type, is there any reason I should not do this?
The primary reason not to do this is, as you said, you've lost your static typing. There are also performance costs associated with it as well, but they're less important than the noticable problem this code has in terms of readability and maintainability.
If it turns out that you misspell or mistype a variable name you don't get compile time checking (and it's easier to do without code completion support). You also don't have any effective means of knowing, at compile time, what variables might exist in the List<object> you're given. It becomes a non-trivial task to track down the source of that list to figure out what variables might be there to use.
It is almost certainly worth the time and effort to create a new named type instead of using an anonymous type when you're in this situation. The small up front cost of creating the new class is virtually always going to pay off.
On top of the type-safety loss & other concerns which have already been pointed out, I feel using dynamic here is just plain wrong.
The general use-case for dynamic is for consuming data from external sources e.g. API/COM etc. basically scenarios where the type of information isn't already clearly defined. In your scenario, you have control over what data you are asking for and you know what type of data to expect therefore I can't really justify why you would want to use it over the benefits gained from having a clearly defined, type-safe model.
Is it unwise to use anonymous object + dynamic?
In your scenario, I would argue yes.
I have the following query, sometimes ExpirationDate is null which blows up the query and the application crashes. If ExpirationDate is null I want to return "" for ExpirationDate. How do I put this if condition in LINQ?
List<PData> pressData =
(from press in dataContext.CPress
where press.ID.ToString() == this.PressID
select new PData
{
Heading = press.Heading,
Description = press.MetaDescription,
DatePublished = press.PublishDate.ToShortDateString(),
ExpirationDate = press.ExpirationDate.Value.ToShortDateString(),
Body = press.BodyContent,
CreatedBy=press.CreatedBy
}).ToList();
UPDATE :
Adding the code Jon suggested I get the following exception
Could not translate expression 'Table(CPress).Where(press =>
(press.PressID.ToString() =
Invoke(value(System.Func`1[System.String])))).Select(press
=> new PData() {Heading = press.Heading, Description =
press.MetaDescription, DatePublished =
press.PublishDate.ToShortDateString(),
ExpirationDate =
IIF((press.ExpirationDate = null), "",
press.ExpirationDate.Value.ToShortDateString()),
Body = press.BodyContent, ID =
press.PressID, CreatedBy =
press.CreatedBy})' into SQL and could
not treat it as a local expression.
Taking ExpirationDate out totally the exception goes away
I'd use:
ExpirationDate = press.ExpirationDate == null ? "":
press.ExpirationDate.Value.ToShortDateString()
EDIT: Having said that, it will only work around the immediate problem. I agree with Nelson's approach of keeping it as a DateTime? and performing the conversion at display time. Aside from anything else, that means you can apply the appropriate culture information etc for the user at that point.
I know it doesn't answer you question directly, but...
If possible, I would keep the date as DateTime?. Usually you want to format it (ToShortDateString(), etc.) whenever you display it, not before.
Edit: Similarly in where press.ID.ToString() == this.PressID: this.PressID would ideally match the type of press.ID. Really, the language is strongly-typed for a reason. If you make all your variables strings, it defeats the whole purpose.
Of course there are some unusual circumstances where you might have to do this and yours may be one of them, but I see no indication that is the case.
Personally I'd go for the option that #Jon Skeet has suggested, but an alternative if you don't like the syntax is to write an extension method and call that
public static string ToShortDateStringOrEmpty(this DateTime? dt)
{
if (dt == null)
return String.Empty;
else
return dt.ToShortDateString();
}
This has the advantage of being neater if you're doing a complex query (such as if the order isn't null, show me the sum of all the line items) and traversing a lot of objects.