I have two GridViews. I've got method GetGeneralDiagnosis which returns a list of all diagnosis:
CODE DIAGNOSIS
F50 Eating disorders
F51 Nonorganic sleep disorders
and method GetSpecificDiagnosis which returns more specific list:
CODE DIAGNOSIS
F50.0 Anorexia nervosa
F50.1 Atypical anorexia nervosa
F51.0 Nonorganic insomnia
F51.1 Nonorganic hypersomnia
Now I've got method which bind SPECIFIC DIAGNOSIS to second GridView according to GENERAL DIAGNOSIS from first GridView.
protected void gvGeneralDiagnosis_SelectedIndexChanged(object sender, EventArgs e)
{
string generalDiagnosis = gvGeneralDiagnosis.DataKeys[gvGeneralDiagnosis.SelectedIndex].Values["ICD10Code"].ToString();
var ICD10 = Visit.GetSpecificDiagnosis(); // here I'm getting data from database
gvSpecificDiagnosis.DataSource = ICD10.Where(i => i.ICD10Code.Contains(generalDiagnosis)).Select(i => new { i.ICD10Name, i.ICD10Code });
gvSpecificDiagnosis.DataBind();
}
I don't want to connect to database each time selected index is changed.
How can i get my list var ICD10 = Visit.GetSpecificDiagnosis() only once? I heard that global variables are very bad idea, so how can I do that in another way?
You can use a private member variable. This one "lives" as long as the class containing it lives. Wrap it with a property to access it and automatically read it from the database, if necessary.
private TypeOfICD10 _icd10;
private TypeOfICD10 ICD10
{
get
{
if (_icd10 == null) { // Get from database.
_icd10 = Visit.GetSpecificDiagnosis();
}
return _icd10;
}
}
Now you can use it like this and it will be read from the db only at the first call
protected void gvGeneralDiagnosis_SelectedIndexChanged(object sender, EventArgs e)
{
string generalDiagnosis = gvGeneralDiagnosis.DataKeys[gvGeneralDiagnosis.SelectedIndex].Values["ICD10Name"].ToString();
gvSpecificDiagnosis.DataSource = ICD10
.Where(i => i.ICD10Code.Contains(generalDiagnosis))
.Select(i => new { i.ICD10Name, i.ICD10Code });
gvSpecificDiagnosis.DataBind();
}
You can have your Visit class cache the returned data.
When GetSpecificDiagnosis is called, it will check whether this data was already retrieved from the database, and return it if it was. If it wasn't, it'll retrieve it from the database and save it to its cache.
One thing you should pay attention to is whether this data is static (i.e. never changes throughout the application's lifetime) or is it dynamic. In the first case, you won't have to do any special handling, but if it's the latter, you'll have to invalidate the cache one the information in the database has changed.
I recommend you to have a look here to see how to get started with caching in ASP.NET.
I don't know much about the Visist class from your question but why not cache ICD10 this way you will be using the cached object and the Database call will made only if the Cache Key ICD10 has a value of null
Example :
if(Cache["ICD10"] == null)
{
var ICD10 = Visit.GetSpecificDiagnosis();
Cache["ICD10"] = ICD10;
}
else
{
var ICD10 = Cache["ICD10"];
}
Related
What I want to do is have the user add items to the list. Then when they add an item I need the list to save, so that when the user closes the app and opens it again, the list they've created is still there.
Right now, I can add items to my list, but as soon as i close the app they will be gone.
private static ObservableCollection<ViewModels.ZoneViewModel> Zones = new ObservableCollection<ViewModels.ZoneViewModel>();
public void PopulateListView(string image, string name, string address)
{
if (name != "" && address != "")
{
Zones.Add(new ViewModels.ZoneViewModel { Image = image, Name = name, Address = address });
Application.Current.Properties["zoneslist"] = Zones;
}
}
protected override void OnAppearing()
{
if (Application.Current.Properties.ContainsKey("zoneslist"))
{
// Put the contents of the "zoneslist" key into a variable as a string.
var savedZones = Application.Current.Properties["zoneslist"] as ObservableCollection<ViewModels.ZoneViewModel>;
// Set the listviews' itemssource to the savedzones list.
zonesList.ItemsSource = savedZones;
}
}
Here's the code I use right now, I thought this could work to save it but that doesn't work.
EDIT: So I've tried what #Alessandro Calario suggested and after using json serialization the listview just gives me a ton of empty list items(even though i only added one). But an item is added and is saved, even when the app is closed. Progress, at least, but I'm not quite there yet. Anyone know a solution?
my code:
public void PopulateListView(string image, string name, string address)
{
if (name != "" && address != "")
{
Zones.Add(new ViewModels.ZoneViewModel { Image = image, Name = name, Address = address });
//Serialize to json string
var json = JsonConvert.SerializeObject(Zones);
Application.Current.Properties["zoneslist"] = json;
}
}
protected override void OnAppearing()
{
if (Application.Current.Properties.ContainsKey("zoneslist"))
{
// Put the contents of the "zoneslist" key into a variable as a string.
var savedZones = Application.Current.Properties["zoneslist"] as string; //ObservableCollection<ViewModels.ZoneViewModel>
JsonConvert.DeserializeObject<ObservableCollection<ViewModels.ZoneViewModel>>(savedZones);
// Set the listviews' itemssource to the savedzones list.
zonesList.ItemsSource = savedZones;
}
}
I think you can Serialize your List of Objects to a json String and save it to Application Properties
If using 3rd parties libraries is not a thing for your project I highly recommend you to use Akavache. This is an Async, persistent key-value store.
Once setup is very simple to use.
//To Insert your object
IObservable<Unit> InsertObject<T>(string key, T value, DateTimeOffset? absoluteExpiration = null);
//To Get your object
IObservable<T> GetObject<T>(string key);
where T can be your whole list.
Of course it's a little more than this but trust me just a little. Read the full documentation and hope it fits your needs.
The Application Properties only stores primitive types.
Note: the Properties dictionary can only serialize primitive types for
storage. Attempting to store other types (such as List can
fail silently).
Source: https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/application-class/
Either set it up so you are using the properties as a primitive storage, or go for another local storage mechanism such as Sqlite (a good guide here: https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/databases/)
I can't sort this weird issue out and I have tried anything and everything I can think of.
I got 5 pages, everyone of them passing variables with navigation this way:
Pass:
NavigationSerice.Navigate(new Uri("/myPage.xaml?key=" + myVariable, UriKind.Relative));
Retrieve:
If (NavigationContext.QueryString.ContainsKey(myKey))
{
String retrievedVariable = NavigationContext.QueryString["myKey"].toString();
}
I open a list on many pages and one of the pages automatically deletes an item from the list actualProject (actualProject is a variable for a string list). Then, when I go so far back that I reach a specific page - the app throws an exception. Why? I have no idea.
The code that deletes the item:
// Remove the active subject from the availible subjects
unlinkedSubjects.Remove(actualSubject);
unlinkedsubjectsListBox.ItemsSource = null;
unlinkedsubjectsListBox.ItemsSource = unlinkedSubjects;
Then the page that throws the exception's OnNavigatedTo event:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (NavigationContext.QueryString.ContainsKey("key"))
{
actualProject = NavigationContext.QueryString["key"];
try
{
//Read subjectList from IsolatedStorage
subjectList = readSetting(actualProject) != null ? (List<String>)readSetting(actualProject) : new List<String>();
//Put the subjectList into the subjectListBox
subjectListBox.ItemsSource = subjectList;
//Set the subjectsPageTitle to the "actualProject" value, to display the name of the current open project at the top of the screen
subjectsPageTitle.Text = actualProject;
}
catch (Exception)
{
if (language.Equals("en."))
{
// Language is set to english
MessageBox.Show("Couldn't open the project, please try again or please report the error to Accelerated Code - details on the about page");
}
else if (language.Equals("no."))
{
// Language is set to norwegian
MessageBox.Show("Kunne ikke åpne prosjektet, vennligst prøv igjen eller rapporter problemet til Accelerated Code - du finner detaljer på om-siden");
}
}
}
}
Exception:
_exception {System.ArgumentException: Value does not fall within the expected range.} System.Exception {System.ArgumentException}
My theory:
The app kind of loads the currently opened and modified List. Is that possible? No idea.
So there are a number of ways to pass data between pages.
The way you have chosen is the least suggested.
You can use the PhoneApplicationService.Current dictionary but this is messy also if you have a ton of variables, doesn't persist after app shut down and could be simplified.
I wrote a free DLL that kept this exact scenario in mind called EZ_iso.
You can find it here
Basically what you would do to use it is this.
[DataContractAttribute]
public class YourPageVars{
[DataMember]
public Boolean Value1 = false;
[DataMember]
public String Value2 = "And so on";
[DataMember]
public List<String> MultipleValues;
}
Once you have your class setup you can pass it easily between pages
YourPageVars vars = new YourPageVars { /*Set all your values*/ };
//Now we save it
EZ_iso.IsolatedStorageAccess.SaveFile("PageVars",vars);
That's it! Now you can navigate and retrieve the file.
YourPageVars vars = (YourPageVars)EZ_iso.IsolatedStorageAccess.GetFile("PageVars",typeof(YorPageVars));
This is nice because you can use it for more than navigation. You can use it for anything that would require Isolated storage. This data is serialized to the device now so even if the app shuts down it will remain. You can of course always delete the file if you choose as well.
Please make sure to refer to the documentation for any exceptions you have. If you still need help feel free to hit me up on twitter #Anth0nyRussell or amr#AnthonyRussell.info
I am writing a asp.net mvc4 app and I am using entity framework 5. Each of my entities have fields like EnteredBy, EnteredOn, LastModifiedBy and LastModifiedOn.
I am trying to auto-save them by using the SavingChanges event. The code below has been put together from numerous blogs, SO answeres etc.
public partial class myEntities : DbContext
{
public myEntities()
{
var ctx = ((IObjectContextAdapter)this).ObjectContext;
ctx.SavingChanges += new EventHandler(context_SavingChanges);
}
private void context_SavingChanges(object sender, EventArgs e)
{
ChangeTracker.DetectChanges();
foreach (ObjectStateEntry entry in
((ObjectContext)sender).ObjectStateManager
.GetObjectStateEntries
(EntityState.Added | EntityState.Modified))
{
if (!entry.IsRelationship)
{
CurrentValueRecord entryValues = entry.CurrentValues;
if (entryValues.GetOrdinal("LastModifiedBy") > 0)
{
HttpContext currContext = HttpContext.Current;
string userName = "";
DateTime now = DateTime.Now;
if (currContext.User.Identity.IsAuthenticated)
{
if (currContext.Session["userId"] != null)
{
userName = (string)currContext.Session["userName"];
}
else
{
userName = currContext.User.Identity.Name;
}
}
entryValues.SetString(
entryValues.GetOrdinal("LastModifiedBy"), userName);
entryValues.SetDateTime(
entryValues.GetOrdinal("LastModifiedOn"), now);
if (entry.State == EntityState.Added)
{
entryValues.SetString(
entryValues.GetOrdinal("EnteredBy"), userName);
entryValues.SetDateTime(
entryValues.GetOrdinal("EnteredOn"), now);
}
else
{
string enteredBy =
entry.OriginalValues.GetString(entryValues.GetOrdinal("EnteredBy"));
DateTime enteredOn =
entry.OriginalValues.GetDateTime(entryValues.GetOrdinal("EnteredOn"));
entryValues.SetString(
entryValues.GetOrdinal("EnteredBy"),enteredBy);
entryValues.SetDateTime(
entryValues.GetOrdinal("EnteredOn"), enteredOn);
}
}
}
}
}
}
My problem is that entry.OriginalValues.GetString(entryValues.GetOrdinal("EnteredBy")) and entry.OriginalValues.GetDateTime(entryValues.GetOrdinal("EnteredOn")) are not returning the original values but rather the current values which is null. I tested with other fields in the entity and they are returning the current value which were entered in the html form.
How do I get the original value here?
I think the problem may be that you are using the instance provided by the model binder as the input to your controller method, so EF does not know anything about that entity and its original state. Your code may look like this:
public Review Update(Review review)
{
_db.Entry(review).State = EntityState.Modified;
_db.SaveChanges();
return review;
}
In that case, EF knows nothing about the Review instance that is being saved. It is trusting you and setting it as modified, so it will save all of its properties to the database, but it does not know the original state\values of that entity.
Check the section named Entity States and the Attach and SaveChanges Methods of this tutorial. You can also check the first part of this article, that shows how EF does not know about the original values and will update all properties in the database.
As EF will need to know about the original properties, you may first load your entity from the database and then update its properties with the values received in the controller. Something like this:
public Review Update(Review review)
{
var reviewToSave = _db.Reviews.SingleOrDefault(r => r.Id == review.Id);
//Copy properties from entity received in controller to entity retrieved from the database
reviewToSave.Property1 = review.Property1;
reviewToSave.Property2 = review.Property2;
...
_db.SaveChanges();
return review;
}
This has the advantage that only modified properties will be send and updated in the database and that your views and view models don't need to expose every field in your business objects, only those that can be updated by the users. (Opening the door for having different classes for viewModels and models\business objects). The obvious disadvantage is that you will incur an additional hit to the database.
Another option mentioned in the tutorial I referenced above is for you to save the original values somehow (hidden fields, session, etc) and on save use the original values to attach the entity to the database context as unmodified. Then update that entity with the edited fields. However I would not recommend this approach unless you really need to avoid that additional database hit.
Hope that helps!
I was running into a similar problem when trying to audit log the Modified values of an Entity.
It turns out during the post back the ModelBinder doesn't have access to the original values so the Model received is lacking the correct information. I fixed my problem by using this function which clones the current values, relods the object, and then reset the current values.
void SetCorrectOriginalValues(DbEntityEntry Modified)
{
var values = Modified.CurrentValues.Clone();
Modified.Reload();
Modified.CurrentValues.SetValues(values);
Modified.State = EntityState.Modified;
}
You can gain access to the DbEntityEntry though the change tracker, or the entry function from your context.
I'm coming from a SQL Server background, and experimenting with Redis in .NET using ServiceStack. I don't mean for Redis to be a full replacement for SQL Server, but I just wanted to get a basic idea of how to use it so I could see where we might make good use of it.
I'm struggling with what I think is a pretty basic issue. We have a list of items that are maintained in a couple of different data stores. For the sake of simplicity, assume the definition of the item is basic: an integer id and a string name. I'm trying to do the following:
Store an item
Retrieve an item if we only know its id
Overwrite an existing item if we only know its id
Show all the items for that specific type
And here's some of the code I've put together:
public class DocumentRepositoryRedis
{
private static string DOCUMENT_ID_KEY_BASE = "document::id::";
public IQueryable<Document> GetAllDocuments()
{
IEnumerable<Document> documentsFromRedis;
using (var documents = new RedisClient("localhost").As<Document>())
{
documentsFromRedis = documents.GetAll();
}
return documentsFromRedis.AsQueryable();
}
public Document GetDocument(int id)
{
Document document = null;
using (var redisDocuments = new RedisClient("localhost").As<Document>())
{
var documentKey = GetKeyByID(document.ID);
if (documentKey != null)
document = redisDocuments.GetValue(documentKey);
}
return document;
}
public void SaveDocument(Document document)
{
using (var redisDocuments = new RedisClient("localhost").As<Document>())
{
var documentKey = GetKeyByID(document.ID);
redisDocuments.SetEntry(documentKey, document);
}
}
private string GetKeyByID(int id)
{
return DOCUMENT_ID_KEY_BASE + id.ToString();
}
}
It all seems to work - except for GetAllDocuments. That's returning 0 documents, regardless of how many documents I have stored. What am I doing wrong?
The typed Redis client also gives you access to the non-typed methods - since Redis ultimately doesn't know or care about your object types. So when you use the client.SetEntry() method, it bypasses some of the typed client's features and just stores the object by a key. You'll want to use the client.Store method since it goes ahead and creates a SET in Redis with all the object IDs related to your type. This SET is important because it's what the GetAll method relies on to serve back all the objects to you. The client.Store method does infer the ID automatically so you'll want to play around with it.
You'd change your GetDocument(int id) and SaveDocument(Document document) methods to use the client.GetById(string id) method, and you'd use client.Store(T value) method. You won't need your GetKeyByID() method anymore. I believe your Document object will need an "Id" property for the typed client to infer your object ID.
I use C# Asp.Net and EF 4.
I have a scenario like MasterPage and DetailsPage.
So from my MasterPage I pass a variable as a QeryString to the DetailsPage, the DetailsPage will show up details for a specifc item in my DataBase.
I need to check the validity for my QueryString, in details I need:
Check if is Null, Empty or White Spaces.
Check if is NOT of type INT (just numbers not any letters).
Check if the Object NOT exists in my DB.
In case if Check result True, I will redirect the User.
At the moment I wrote this script. It is works but I would like to know if you know a better approch/code to solve this.
Also I would like to know if make sense to have this logic on every time the page Load, or would be enought us just on !Page.IsPostBack.
Thanks once again for your support guys!
protected void Page_Load(object sender, EventArgs e)
{
#region Logic Check Query String.
// Query String is Null or Empty.
if (string.IsNullOrWhiteSpace(ImageIdFromUrl))
RedirectToPage();
// Query String is not valid Type of INT.
int ImageId;
bool isInt = Int32.TryParse(ImageIdFromUrl, out ImageId);
if (isInt)
{
// Check if a valid Object request exist in Data Source.
using (CmsConnectionStringEntityDataModel context = new CmsConnectionStringEntityDataModel())
{
if (!context.CmsImagesContents.Any(x => x.ImageContentId == ImageId))
{
RedirectToPage();
}
}
}
else
RedirectToPage();
#endregion
}
You don't need to check it on every postback, only on a full page load. The query string is not sent to the server on postbacks.
I suggest you move all the query string validation logic to separate functions.