I have a session helper so that my session vars are strongly typed:
public sealed class SessionHelper
{
private static HttpSessionState Session
{
get
{
return HttpContext.Current.Session;
}
}
public static List<TestObject> Tests
{
get
{
List<TestObject> objects = new List<TestObject>();
if (Session["Tests"] != null)
{
objects = (List<TestObject>)Session["Tests"];
}
return objects;
}
set
{
Session["Tests"] = value;
}
}
}
Now I am trying to add an item to theTestObjects List so I thought I could just do:
SessionHelper.Tests.Add(new TestObject("Test name", 1));
But when I step through the code and look at the SessionHelper.Tests after the above line is run, the list count remains at 0.
If I do:
List<TestObject> tests = SessionHelper.Tests;
tests.Add(new TestObject(testName, version));
SessionHelper.Tests = tests;
Then it works properly.
Why can't I add the test object directly to the SessionHelper?
Session["Tests"] is null when you start. Therefore SessionHelper.Tests returns a new, empty list; however, this new list is not in the session object yet. Therefore SessionHelper.Tests will return a new, empty list every time. Store the new list in the session object after creating it.
public static List<TestObject> Tests
{
get
{
List<TestObject> objects = (List<TestObject>)Session["Tests"];
if (objects == null)
{
objects = new List<TestObject>();
Session["Tests"] = objects; // Store the new list in the session object!
}
return objects;
}
set // Do you still need this setter?
{
Session["Tests"] = value;
}
}
Related
I'll try to resume everything as much as possible:
I have a class that creates a dictionary (let's call it secondary dictionary) with the initial values of some of the elements of another dictionary, (for simplicity, let's call it the main dictionary and this class does this only once) and then a thread that checks every x miliseconds against this main dictionary, that's being regularly updated every y miliseconds, for any changes on the elements that where stored in the initialization phase.
My problem is, that when I want to compare the values of element1 in the main dictionary against the value of element1 in the secondary dictionary, they're always the same, (I undersatnd that, until the main dictionary is nnot updated, both values will be the same, but when the main dictionary gets updated, so does the second, immediately, without me doing anything)
I've tried ConcurrentDictionaries, using locks, a combination of boths, creating a new element in the initialize functions instead of passing it directly, but nothing seems to work
class Checker
{
private static bool secondaryDictionaryHasChanged = false;
private static ConcurrentDictionary<int, ValueDTO> secondaryDictionary = new ConcurrentDictionary<int, ValueDTO>();
public Checker()
{
initSecondaryDictionary();
Thread checkChangedValsThread = new Thread(() => checkChangedValsThreadFunction(1000));
checkChangedValsThread.Start();
}
public void initSecondaryDictionary()
{
Object MainLock = new Object();
lock (MainLock)
{
Object secondaryLock = new Object();
lock (secondaryLock)
{
foreach (var variable in Maindictionary)
{
if (variable.isElegibleValue)
{
ValueDTO ValueDTOToAdd = new ValueDTO();
ValueDTOToAdd.EligibleVar = variable;
if (variable.contextVariables.Count > 0)
{
List<Var> contextVariablesToAdd = new List<Var>();
foreach (var item in variable.contextVariables)
{
contextVariablesToAdd.Add(getVarFromMainDictionary(item));
}
ValueDTOToAdd.ContextVars = contextVariablesToAdd;
}
secondaryDictionary.TryAdd(ValueDTOToAdd.EligibleVar.varCode, ValueDTOToAdd);
}
}
}
}
secondaryDictionaryHasChanged = false;
}
public void checkChangedValsThreadFunction(int checkTime)
{
while (true)
{
try
{
if (!secondaryDictionaryHasChanged)
{
Thread.Sleep(checkTime);
Object mainLock = new Object();
lock (mainLock)
{
Object secondaryLock = new Object();
lock (secondaryLock)
{
foreach (var item in secondaryDictionary)
{
ValueDTO secondaryDictionaryDTO = item.Value;
Var variableInSecondary = secondaryDictionaryDTO.EligibleVar;
Var variableInMain = getVarFromMainDictionary(item.Value.EligibleVar.varID);
int valueInMain = variableInMain.getIntValue();
int valueInSecondary = variableInSecondary.getIntValue();
if (valueInMain != valueInSecondary)
{
//IT NEVER ENTERS THIS HERE
}
}
}
}
}
}
catch (Exception e)
{
throw new Exception("Some exception: " + e.Message);
}
}
}
}
internal class ValueDTO
{
public Var EligibleVar { get; set; }
public List<Var> ContextVars { get; set; }
}
internal class Var
{
public int varCode { get; set; }
public string varID { get; set; }
}
I add a reduced version of the code I have the thing is that it will never go inside that if(mainValue != secondaryValue)
any help or info about where I'm going wrong will be deeply appreciated
As fildor already said, you have one object and two references to it.
To simplify your problem I created a short sample:
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public class Example
{
class Person
{
public string Name
{
get;
set;
}
}
public static void Main()
{
var myPerson = new Person();
myPerson.Name = "User1";
var list1 = new List<Person>();
var list2 = new List<Person>();
// put a reference to myPerson into each of the lists
list1.Add(myPerson);
list2.Add(myPerson);
// get the reference to myPerson from list1
var myPersonInList1 = list1[0]
myPersonInList1.Name = "User2";
// this will print User2 because there is only one person object
Console.WriteLine(list2[0].Name);
}
}
Basically no matter where you pass the Person, it will always be a reference to the Person instance you created. All changes to it will apply to the object behind the reference. All references point to the same object.
A bit more in depth knowledge very simplified, but I hope you'll get the point:
There is a stack and a heap storage. The stack contains value types and references and the heap contains objects.
Stack:
Variable | Value
--------------------
myPerson | #abc123
list1[0] | #abc123
list2[0] | #abc123
myInt | 42
Heap:
Address | Value
-------------------
abc123 | { Name: "User2" }
Now every time you create a variable pointing to myPerson, you only create a new entry in the stack, pointing to the same object in the heap. Now, of course when you update the object behind the reference and set its name to "User1", all references will display the change.
I have created a shopping cart using session to store the item being added to cart.Upon deployment i found out that the shopping cart is not unique to the user that is other user are getting items added to the cart by other user.
I tried to use the login username in the session name to make the session unique to that user but it is not working.
public class ListOfDataset
{
static ListOfDataset()
{
string username = ClaimsPrincipal.Current.Identity.Name;
// If the cart is not in the session, create one and put it there
// Otherwise, get it from the session
if (HttpContext.Current.Session[string.Format("ASPNETShoppingCart-{0}", username)] == null)
{
Instance = new ListOfDataset();
Instance.Items = new List<DataSet>();
HttpContext.Current.Session[string.Format("ASPNETShoppingCart-{0}", username)] = Instance;
}
else
{
Instance = (ListOfDataset)HttpContext.Current.Session[string.Format("ASPNETShoppingCart-{0}", username)];
}
}
}
Updated code,error in else statement-object reference not set and function ChekIfdatasetexist always return false:
public class ListOfDataset
{
public static ListOfDataset Instance
{
get
{
ListOfDataset cart = null;
if (HttpContext.Current.Session["ASPNETShoppingCart"] == null)
{
cart = new ListOfDataset();
cart.Items = new List<DataSet>();
HttpContext.Current.Session["ASPNETShoppingCart"] = cart.Items;
}
else
{
cart.Items =(List<DataSet> )HttpContext.Current.Session["ASPNETShoppingCart"];
}
return cart;
}
}
public List<DataSet> Items { get; private set; }
public void AddItem(DataSet itemdataset)
{
Items.Add(itemdataset);
HttpContext.Current.Session["ASPNETShoppingCart"] = Items;
}
public bool CheckIfDataSetExist(string servicename)
{
DataSet DataSetexist = null;
if (Items != null)
{
DataSetexist = Items.Where(i => i.DataSetName == servicename).FirstOrDefault();
}
if (DataSetexist != null) return true;
return false;
}
}
There are two issues here.
As someone said in comments you have made the Instance member static, which means it will remain the same application wide and shared among users.
Session is not the best place to store per user data cause it will blow up your server memory and wont scale. Better use a database to store the data.
I am building xamarin forms app, I am using jamesmontemagno settings plugin and I'm adding a property which list of a class. But the thing is I'm not able to add or insert to the list, every time I use method Add or Insert it jump into the get not the set and I can't understand why.
here is my code and thanks for the help in advance:
//adding an item to the list
private void order(Sales_Order_Items sale)
{
orderlist.Add(sale);
Settings.Usercartlist.Add(sale);
}
I can only set it by using this code
Settings.Usercarlist=orderlist;
the property in the settings file
public static List<Sales_Order_Items> Usercartlist
{
set
{
string listValue = JsonConvert.SerializeObject(value);
AppSettings.AddOrUpdateValue(myIntListKey, listValue);
}
get
{
string value = AppSettings.GetValueOrDefault(myIntListKey, string.Empty);
List<Sales_Order_Items> myList;
if (string.IsNullOrEmpty(value))
myList = new List<Sales_Order_Items>();
else
myList = JsonConvert.DeserializeObject<List<Sales_Order_Items>>(value);
return myList;
}
}
When adding an item, the actual object reference does not change. Only the value changes. This is not picked up by the getter or setter.
The only way to update after each item is to add the line you already have: Settings.Usercarlist=orderlist; after each operation.
I am using like the following way you can try that
Ex.
private static UserDetails _currentUser = null;
public static UserDetails CurrentUser
{
get
{
if (_currentUser == null)
{
string data = AppSettings.GetValueOrDefault(nameof(CurrentUser), string.Empty);
if (data != null)
_currentUser = JsonConvert.DeserializeObject<LoginResponse>(data);
}
return _currentUser;
}
set
{
string data = JsonConvert.SerializeObject(value);
AppSettings.AddOrUpdateValue(nameof(CurrentUser), data);
_currentUser = value;
}
}
When an object hold another object as a property and that property is by default null. Will that property be initialized if its own property's get accessed by code?
public User {
private _obj = null;
public Obj SomeObject {
get { return _obj ?? (_obj = new Obj()); }
set { _obj = value; }
}
public User() {
//do stuff
}
}
Code Being used.
User user = new User();
int x = user.SomeObject.SomeIntValue;
Would this initiate a new version of SomeObject if it was null?
-- Edit --
Applied #Kjartan suggestion to code.
This will indeed work. The first time the property will get accessed, _obj will be filled with the new instance (since it was null before). Next calls, you will return the same Obj instance that was initialized the first time.
This is a common way for creating some sort of "lazy-loading".
Should work. And as a side-note, just for brevity you could replace this:
get {
if(_obj == null)
_obj = new Obj();
return _obj;
}
...with this:
get { return _obj ?? (_obj = new Obj()); }
is it possible in Db4o to load new objects into persistent IObjectContainer?
I have a desktop application which opens one connection (IObjectContainer) when started. if I query all objects with:
var objects = from DummyClass foo in session
select foo
it selects all objects perfectly. However, if another client adds new classes after this, the same query still selects the same objects, without new ones.
I also know about:
session.Ext().Refresh(obj, int.MaxValue);
but I don't have even not activated references to new objects so there. How to refresh new objects?
Just note: I don't want to open/close session every time I need some data, I want to take advantage of OODB (Transparent activation, object persistance since loaded etc.)
Thank you
UPDATE (code example for better understanding)
// store one class to fill database with some data
using (var mainSession = SessionFactory.CreateNewConnection())
{
mainSession.Store(new DummyClass());
mainSession.Commit();
}
using (var mainSession = SessionFactory.CreateNewConnection())
{
// returns one object
var objects = from DummyClass foo in session
select foo;
using (var secondSession = SessionFactory.CreateNewConnection())
{
secondSession.Store(new DummyClass());
secondSession.Commit();
}
// this loop reload objects known for mainSession (which is not new object)
foreach (var obj in objects2)
{
mainSession.Ext().Refresh(obj, int.MaxValue);
}
// new DummyClass is commited but still not visible (Read-Commited isolation)
// returns one object
var objects2 = from DummyClass foo in session
select foo;
}
using (var mainSession = SessionFactory.CreateNewConnection())
{
// returns two objects
var objects = from DummyClass foo in session
select foo;
}
I need something like:
// refresh all objects of DummyClass
session.Ext().Refresh(typeof(DummyClass), int.MaxValue);
You may use Commited events:
using Db4objects.Db4o;
using Db4objects.Db4o.Events;
using Db4objects.Db4o.IO;
using Db4objects.Db4o.Ext;
namespace PushedUpdates
{
class Program
{
static void Main()
{
var config = Db4oEmbedded.NewConfiguration();
config.File.Storage = new MemoryStorage();
var container = Db4oEmbedded.OpenFile(config, "IN-MEMORY");
var client = container.Ext().OpenSession();
var clientEvents = EventRegistryFactory.ForObjectContainer(client);
clientEvents.Committed += (s, a) =>
{
foreach(IObjectInfo added in a.Added)
{
System.Console.WriteLine(added.GetObject());
}
};
container.Store(new Item { Value = 1 } );
container.Commit();
container.Store(new Item { Value = 2 });
container.Commit();
container.Store(new Item { Value = 3 });
container.Commit();
client.Close();
container.Close();
}
}
class Item
{
public int Value { get; set; }
public override string ToString()
{
return "" + Value;
}
}
}
Did your client call the commit() method after storing the data? Otherwise the new data will not be available for other clients.