"Value can not be null" error in Singleton pattern - c#

I have a class that implements singleton pattern as you can see below:
public class SearchSingletonObject
{
private static SearchSingletonObject foundation = null;
public SearchObject Object= null;
private static StringCollection views = null;
private static object control = new object();
public IEnumerable<string> blacklist = null;
public static void ClearFoundation()
{
foundation = null;
}
public static SearchSingletonObject Foundation
{
get
{
if (foundation == null)
{
lock (control)
{
if (foundation == null)
{
foundation = new SearchSingletonObject();
var blacks = File.ReadAllText(HostingEnvironment.ApplicationPhysicalPath + "\\blacklist.txt");
foundation.blacklist = blacks.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrEmpty(x) || x != " ");
views = new StringCollection();
var items = ConfigurationManager.AppSettings["SearchView"].Split(',');
foreach (var item in items)
{
views.Add(item);
}
foundation.Object = new SearchObject(ConfigurationManager.AppSettings["ContentDistributor"],
ConfigurationManager.AppSettings["Port"],
views);
}
}
}
return foundation;
}
}
public SearchSingletonObject()
{
}
}
We're using this class in our wcf rest services. But in non-periodic intervals we get "Value can not be null" errors. Here is my log file:
08.03.2011 11:40:39 ERROR Message : Value cannot be null.
Parameter name: source
StackTrace : at System.Linq.Enumerable.Where[TSource](IEnumerable`1 source, Func`2 predicate)
at Search.Service.SearchService.Search(String keyword, Int32 offset, Int32 hit, String navstate, String username, Boolean issecure, Int32 suggest, String sortref, String fields, Int32 IsFirstSearch, String misspelled, String category) in D:\tfs\Hey\HeyRestApi\HeyService\HeyService.cs:line 68
Log file mentions the row below in my service:
var blacks = SearchSingletonObject.Foundation.blacklist.Where<string>(x => item.Equals(x)).FirstOrDefault();
It seems strangely the "blacklist" object getting null value. After the error, we have to reset IIS, to get application working. We can not reproduce the error on our local servers. It just happens in our customers production environment.
How can we solve that problem and what can be the reason of this strange error?
Thanks in advance,

Double-checked locking is broken.
Short explanation:
Even if foundation is non-null, without a lock you can't be sure that foundation's members are non-null from the point of view of your processor.
You need to remove the if statement that's outside the lock.
Update
A better solution is to mark foundation as volatile:
private static volatile SearchSingletonObject foundation = null;
The need for volatile modifier in double checked locking in .NET has more details.

Related

How to check if IDataReader is closed by using the .net compiler API

I am trying to write a code analyzer that will check if there are any IDataReaders that are not closed.
I have gone through this question but it does not explain how it can be done, I have also tried to read through the documentation in the github link The English language used here is too complicated and I did not understand how I will be able to find all instances of type IDataReader and verify that the method close() is being called on it before any variable of the said type goes out of scope.
I have tried creating a project of type Analyzer with code fix in visual studio, I tried to register the operation context in the Initialize method of my class (Which is extended from the type DiagnosticAnalyzer as follows:
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class DataReaderAnalyzerAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "DataReaderAnalyzer";
private static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.AnalyzerTitle), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.AnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources));
private static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.AnalyzerDescription), Resources.ResourceManager, typeof(Resources));
private const string Category = "DBConnectionCheck";
private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Error, isEnabledByDefault: true, description: Description);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }
public override void Initialize(AnalysisContext context)
{
context.RegisterOperationAction((operationContext) =>
{
((Microsoft.CodeAnalysis.CSharp.Syntax.AssignmentExpressionSyntax)((Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax)operationContext.Operation.Syntax).Expression).Left
}
, OperationKind.ExpressionStatement);
}
}
I want to find all the references of the occurrence of the variable that holds the type IDataReader, make sure that the close method is being called in this variable before it is lost out of scope.
A sample of my code that I would like to analyze is as follows.
class Program
{
static void Main(string[] args)
{
IDataReader reader = null;
try
{
Database db = DatabaseFactory.CreateDatabase("ApplicationConnection");
reader = GetDataReader(db);
while (reader.Read())
{
//Do somethig with the data here
}
reader.Close();
}
catch (Exception)
{
throw;
}
finally
{
if (reader != null && !reader.IsClosed)
{
reader.Close();
}
}
}
public static IDataReader GetDataReader(Database db)
{
DbCommand dbcmd = db.GetSqlStringCommand("some select statement to get data from oracle data base");
var reader = db.ExecuteReader(dbcmd);
return reader;
}
}
Ultimately, the code shown isn't great, and IMO it would be the wrong solution to write an analyzer to enforce it.
There is a very simple way of doing this style of operation, and it mostly involves forgetting about Close, and using the fact that it is IDisposable - which is the intended API for this kind of scenario. Then it becomes much, much simpler - so much simpler that a: you don't need a special analyzer for it, and b: existing analyzers that work against IDisposable probably do the job for you.
using var reader = GetDataReader(db);
while (reader.Read())
{
//Do somethig with the data here
}
with no try/catch/finally etc; the compiler will add everything you need for this to do the right thing, simply via the using. Note that with older compilers, this needs to be:
using (var reader = GetDataReader(db))
{
while (reader.Read())
{
//Do somethig with the data here
}
}
As a side note: I would strongly suggest not fighting the ADO.NET API - it isn't a useful way of spending your time; tools like Dapper do most common things for you, so you don't need to write this code - and it knows all the corner cases to avoid.
A typical Dapper usage might be:
string region = ...
var users = connection.Query<User>(
"some * from Users where Region = #region",
new { region } // parameters
).AsList();
with the library dealing with all the ADO.NET details internally.
The below code is a non battle hardened approach you can follow.
analysisContext.RegisterCompilationStartAction(compilationContext =>
{
var variables = new HashSet<string>();
var tree = compilationContext.Compilation.SyntaxTrees.First();
//iterate over all childnodes starting from root
foreach (var node in tree.GetRoot().ChildNodes())
{
var flat = Flatten(node).ToList();
//find all variable declarations
var varDecls = flat.OfType<VariableDeclarationSyntax>();
foreach (var decl in varDecls)
{
if (!(decl.Type is IdentifierNameSyntax id)) continue;
if (!id.Identifier.Text.Equals("IDataReader")) continue;
//if you are declaring an IDataReader, go store the var name in set
foreach (var reader in decl.Variables)
{
variables.Add(reader.Identifier.Text);
}
}
//find all method calls i.e. reader.Read() etc
var invokes = flat.OfType<InvocationExpressionSyntax>();
foreach (var invoke in invokes)
{
var memberAccess = invoke.Expression as MemberAccessExpressionSyntax;
var ident = memberAccess.Expression as IdentifierNameSyntax;
if(!variables.Contains(ident.Identifier.Text)) continue;
var name = memberAccess.Name as IdentifierNameSyntax;
//if we find any Close() method on reader, remove from var set
if (name.Identifier.Text.Equals("Close"))
{
variables.Remove(ident.Identifier.Text);
}
}
}
// if we have any variables left in set it means Close() was never called
if (variables.Count != 0)
{
//this is where you can report
//var diagnostic = Diagnostic.Create(Rule, location, value);
//context.ReportDiagnostic(diagnostic);
}
});
public static IEnumerable<SyntaxNode> Flatten(SyntaxNode node)
{
yield return node;
var childNodes = node.ChildNodes();
foreach (var child in childNodes)
foreach (var descendant in Flatten(child))
yield return descendant;
}

C# Command parser

im currently expanding my knowledge a little, and wanted to Create a little game for myself.
The Structure is as Following:
Programm.cs creates an instance of Gamecontroller. This Gamecontroller is the lowest level i want to Access. It will create instaces of the Views, and from classes like config.
I want to implement an debug Console with Command Input. These Commands should always start at the Gamecontroller level, and should be able to interact with kinda everything i could do with C# code.
So i want to access the Objects, Member and methods withing Gamecontroller, or Within any nested object.
Currently i cant get to the Properties of an Child, because _member returns an "Type" which gets parsed to RuntimeProperty instead of the Class
Example on Parsing:
"objPlayer.name" > "GameController.objPlayer.name"
"objConfig.someSetting = 10" > "GameController.objConfig.someSetting=10"
"objConfig.functionCall()" > "GameController.objConfig.functionCall()"
"objConfig.objPlayer.setName("someName")" > "GameController.objConfig.objPlayer.setName("someName")"
"objPlayer.name" > "GameController.objPlayer.name"
this is what i got so far:
private void parseComamnd(string Command)
{
var actions = Command.Split('.');
var start = this.GetType();
var last = actions[actions.Length - 1];
foreach (var action in actions)
{
if (action.Contains("(") && action.Contains(")"))
{
_exec(start, action);
}
else
{
start = _member(start, action);
}
}
}
private Type _member(Type pHandle, string pStrMember)
{
return pHandle.GetProperty(pStrMember).GetType();
}
private void _exec(Type pHandle, string pStrFunction)
{
var Regex = new Regex(#"\(|,|\)");
var FunctionParams = Regex.Split(pStrFunction);
var FunctionName = FunctionParams[0];
FunctionParams[0] = "";
FunctionParams = FunctionParams.Where(val => val != "").ToArray();
pHandle.GetMethod(FunctionName).Invoke(FunctionName, FunctionParams);
}
If I understood right, you want to match some string commands with actions you want to perform. In this case you could use Dictionary as a storage for string-delgate couples to match your string commands to actions you want to perform. As an advantage of this approach, you can change matched couples during program runtime as you wish
class SomeClass
{
delegate void OperationDelegate(string value);
IDictionary<string, OperationDelegate> Operations = new Dictionary<string, OperationDelegate>();
public SomeClass()
{
Operations.Add("objPlayer.name", SetName);
Operations.Add("objConfig.someSetting", SetSetting);
}
public void HandleNewValue(string command, string value)
{
try
{
if (Operations.ContainsKey(command))
Operations[command](value);
}
catch (Exception e)
{
Logger.Error(e);
}
}
private void SetName(string value)
{
// Some logic there
}
private void SetSetting(string value)
{
// Some logic there
}
}

Enum Bound to Database

When writing code for existing applications, often times the development database environment does not match the production environment - and even worse, there are times still where overlaying the environments is just not an option.
One idea I had in mind to code for all environments would be to use a databound enum, whose values would be bound to the ID of the data item they represent. I couldn't get that to work with an Enum but I was able to solve it via abstract classes. For example:
public abstract class Colors
{
private static readonly string c_red = "red";
private static readonly string c_blue = "blue";
private static readonly string c_yellow = "yellow";
private static readonly string c_green = "green";
private static int? _red = null;
private static int? _blue = null;
private static int? _yellow = null;
private static int? _green = null;
public static int Red
{
get
{
if (_red == null)
_red = GetColorID(c_red);
return (int)_red;
}
}
public static int Blue
{
get
{
if (_blue == null)
_blue = GetColorID(c_blue);
return (int)_blue;
}
}
public static int Yellow
{
get
{
if (_yellow == null)
_yellow = GetColorID(c_yellow);
return (int)_yellow;
}
}
public static int Green
{
get
{
if (_green == null)
_green = GetColorID(c_green);
return (int)_green;
}
}
private static int GetColorID(string identifier)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["Demo"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("spGetColorId", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("Name", identifier);
return Convert.ToInt32(cmd.ExecuteScalar());
}
}
}
}
By doing it this way, I'm able to call Colors.Red in this example to get the ID of Red regardless of if I'm in Dev, Testing, or Production.
My question is: is this really the ideal method of accomplishing this? Is there a native-to-C# method of databinding enums, or something equivalent to what I'm doing above?
Having an enum implies that the values are rarely, if ever, changes. you can think of it as a closed list of values (like days of the week etc.).
Because of this nature of enums, I find it acceptable to have this redundancy of having the enum underlying value being specified twice (once in the DB and the other in the enum itself).
If you are worried about discrepancies, you can run a validation for the values when your application starts and check that the values has the correct corresponding ids and that the number of values in the enum matches the number of values in the DB.

Can't add to a list within a class object

First, I'm going to apologize if this is a stupid question. I've been using C# for 16 hours after having not programmed anything since VB6. I'm just trying to hack together a small program for personal use that reads from an old access database and spits out a formatted report in Excel. I apologize for the messy/inefficient code.
Overview: I have two class types, "Zone" and "Device". Each "Zone" has a List of Devices in it. The main program has a List of Zones. Each database has a varying number of "zones" in it, and each "zone" has a varying number of devices assigned to it. I need to parse, sequentially, the zone list and the devices on each zone. I started with structs and arrays and popular opinion seems to be that those are both bad ways to do it, and I wasn't having much luck anyway, so I moved to lists and classes, and it was going well.
I can pull all the "zones" from the database, add them to the list, assign them their labels and IDs. The problem is when I go to read the "devices" from the database, I can't add them to the list within the Zone.
This is the error I get: "Object reference not set to an instance of an object." Which I gather means the object is null?
Here's the relevant code:
Device Class:
public class Device
{
public string Label;
public string Address;
public string Type;
public Device(string Label, string Address, string Type)
{
this.Address = Address;
this.Label = Label;
this.Type = Type;
}
}
Zone Class:
public class Zone
{
public string Label;
public short ID;
public List<Device> Devices;
public Zone(string Label, short ID) {
this.Label = Label;
this.ID = ID;
// ADDED AS PER SUGGESTIONS BELOW
this.Devices = new List<Device>();
}
// Added this to see if it would work, it would not.
public void AddDevice(string Label, string Address, string Type) {
Devices.Add(new Device(Label, Address, Type));
}
}
Initializing and populating Zone List (on button click) (completes successfully)
List<Classes.Zone> Zones = new List<Classes.Zone>();
dbZoneReader = myZoneSelect.ExecuteReader();
while (dbZoneReader.Read())
{
Classes.dbItem dbRow = new Classes.dbItem();
dbRow.Address = Convert.ToInt16(dbZoneReader["DeviceAddress"].ToString());
dbRow.DeviceType = Convert.ToInt16(dbZoneReader["DeviceType"].ToString());
dbRow.Label = dbZoneReader["DeviceLabel"].ToString();
if (dbRow.Label != "" && dbRow.Address > 0)
{
Zones.Add(new Classes.Zone(dbRow.Label,dbRow.Address));
}
}
Adding Devices to their respective Zones:
while (dbReader.Read()) {
Classes.dbItem dbRow = new Classes.dbItem();
string tempZones;
// Acquire/convert device information
dbRow.Node = Convert.ToInt16(dbReader["NodeAddress"].ToString());
dbRow.Loop = Convert.ToInt16(dbReader["LoopSelection"].ToString());
dbRow.Address = Convert.ToInt16(dbReader["DeviceAddress"].ToString());
dbRow.TypeID = Convert.ToInt16(dbReader["TypeID"].ToString());
dbRow.FlashScanID = Convert.ToInt16(dbReader["FlashScanID"].ToString());
dbRow.DeviceType = Convert.ToInt16(dbReader["DeviceType"].ToString());
dbRow.Label = dbReader["DeviceLabel"].ToString();
// Find "proper" zone ID (some zones have multiple IDs, only one is relevant)
tempZones = dbReader["DevicePointMappingList"].ToString();
tempZones = tempZones.Replace("Z", "");
var elements = tempZones.Split(new[] { ',' }, System.StringSplitOptions.RemoveEmptyEntries);
if (elements.Length >= 2) {
ZoneCheck z = new ZoneCheck();
foreach (string items in elements) { if (z.Check(items)) { dbRow.Zone = Convert.ToInt16(items); } }
} else {
if (elements.Length == 1) { dbRow.Zone = Convert.ToInt16(elements[0]); }
else { dbRow.Zone = 0; }
}
// Only add devices that aren't assigned to zone 0, which is non-existent
if (dbRow.Zone > 0) {
// Add new device to zone's device list [THIS IS WHERE IT FAILS]
Zones.Find(z => z.ID == dbRow.Zone).Devices.Add(new Classes.Device("Test", "test", "Test"));
}
}
I've gone through and found out exactly where it fails, and it's the last line where it tries to add the device. Searching here and on google has lead me to believe that I need to initialize the object list... which I believe I've done? I've tried initializing it within the Zone class constructor, and when the Zone is added (which is what it's set too now).
I've confirmed that the Zone object exists, and that the Detectors list within that Zone object isn't null. Kinda stumped, figure I'm doing something that I shouldn't be doing and just don't know better, or I'm missing something really obvious.
The problem is in your Zone class. You need to initialize the List<Device> as follows.
public class Zone
{
public string Label;
public short ID;
public List<Device> Devices;
public Zone(string Label, short ID) {
this.Label = Label;
this.ID = ID;
this.Devices = new List<Device>();
}
// Added this to see if it would work, it would not.
public void AddDevice(string Label, string Address, string Type) {
Devices.Add(new Device(Label, Address, Type));
}
}
The reason is that when you write public List<Device> Devices;, you're not actually creating an object. You're creating a variable that can hold an instance of the specified object. It's only when you pair the variable declaration up with object initialization ( = new List<Device>();) that you get a usable instance of the object.
Thinking of the same issue in terms of a simpler object may help:
public class Foo
{
public string bar; // bar isn't an actual instance of an object, it's just a spot that can hold a string
public void ManipulateBarWithRuntimeError()
{
bar.Substring(0, 1); // "bar" isn't actually set to anything, so how can we take a substring of it? This is going to fail at runtime.
}
public void ManipulateBarWithoutRuntimeError()
{
bar = "Hello, world!";
bar.Substring(0, 1); // bar is actually set to a string object containing some text, so now the Substring method will succeed
}
}
I think the problem is in your Zone class.
Here is my version of your Zone class:
public class Zone
{
public string Label;
public short ID;
public List<Device> Devices;
public Zone(string Label, short ID) {
this.Label = Label;
this.ID = ID;
this.Devices = new List<Device>();
}
// Added this to see if it would work, it would not.
public void AddDevice(string Label, string Address, string Type) {
Devices.Add(new Device(Label, Address, Type));
}
}
This is an only change that I made to your class;
this.Devices = new List<Device>();
Now it might work...
You can also initialize the list inside a getter
public class Zone
{
public string Label;
public short ID;
private List<Device> _devices;
public List<Device> Devices
{
get
{
return this._devices ?? (this._devices = new List<Device>());
}
}
public Zone(string Label, short ID)
{
this.Label = Label;
this.ID = ID;
}
// Added this to see if it would work, it would not.
public void AddDevice(string Label, string Address, string Type)
{
Devices.Add(new Device(Label, Address, Type));
}
}

Need help identifying a subtle bug.. in IIS? The Session? Elsewhere..?

I have a very subtle bug that I'm having trouble identifying.
Background:
We have 2 sites running off the same application on the same web server.
SiteA -- accessed by www.SiteA.com
SiteB -- accessed by www.SiteB.com
When the request first comes in, the siteId is identified based on the Host and stored in the Session as follows:
protected void Application_BeginRequest(object sender, EventArgs e)
{
string host = Request.Url.Host;
int siteId = new SiteManager().GetSiteByUrl(host).SiteId;
if (SessionUser.Instance().SiteId != siteId)
{
SessionUser.Instance().SiteId = siteId;
}
}
This ID used later in determining what data to retreive and to determine what style to present:
// this happens during an initialization phase
_siteConfiguration = _siteManager.GetSiteById(SessionUser.Instance().SiteId);
// then later:
private void SetPageTheme()
{
string theme = null;
switch (_siteConfiguration.SiteId)
{
case ConfigurationHelper.SITE.A:
theme = "SiteATheme";
break;
case ConfigurationHelper.SITE.B:
theme = "SiteBTheme";
break;
}
Page.Theme = theme;
}
The problem:
the problem I'm facing is if you load both sites at almost exactly the same time, i.e. within milliseconds, sometimes SiteA will load with SiteB's theme and vice versa. This doesn't happen very often but it has come to the attention of the client so it's now a problem.. Something is happening somewhere within those few milliseconds in the difference between SiteA loading and SiteB loading, and I don't know how to identify what that is.
The question:
Does anyone have any ideas what could be going wrong here? Something is getting confused somewhere. Is it IIS mixing up the requests? Is it the Session mixing up the site it's supposed to return the SiteId for?
If any more info is needed, I'll supply it.
Update:
For reference, this is the definition of SessionUser (basically, create a static instance of an object to get the SiteId value from the Session):
public class SessionUser
{
private static SessionUser _instance;
public int SiteId { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public static SessionUser Instance()
{
if (null == _instance)
{
_instance = new SessionUser();
if (null != HttpContext.Current.Session)
{
if (null == HttpContext.Current.Session["User"])
{
if (HttpContext.Current.Request.QueryString["sid"] != null)
{
int nSiteId = int.Parse(HttpContext.Current.Request.QueryString["sid"]);
_instance.SiteId = nSiteId;
HttpContext.Current.Session["User"] = _instance;
}
}
else
{
_instance = (SessionUser) HttpContext.Current.Session["User"];
}
}
}
return _instance;
}
}
Without knowing what the 'SessionUser' class looks like, I can only speculate.
I will assume that SessionUser.Instance() returns a 'static' instance (or member rather).
Now, these will be shared across the entire application. So it makes sense that this cannot be shared between 2 sites.
I suggest you rather use HttpContext to store the setting at BeginRequest.
The code will then look like the following:
class SessionUser
{
public static SessionUser Instance()
{
var ctx = HttpContext.Current;
var su = ctx["SessionUser"] as SessionUser;
if (su == null)
{
ctx["SessionUser"] = su = new SessionUser();
}
return su;
}
}
I guess you could put the code that stores the current Site ID inside a lock block, but this may hamper performance. It makes more sense to use something not shared by both sites, as leppie says.
For the lock example:
if (SessionUser.Instance().SiteId != siteId)
{
lock(somePrivateStaticObject)
{
if (SessionUser.Instance().SiteId != siteId)
{
SessionUser.Instance().SiteId = siteId;
}
}
}

Categories