Updating data in Firebase deletes unused values - c#

I have the following database in Firebase:
Whenever I try to update some items, it deletes the unaltered ones, instead of letting them keep their values. I have the following code:
FirebaseClient firebaseClient = new FirebaseClient("FirebaseLink");
MyDatabaseRecord databaserecord = new MyDatabaseRecord
{
Plate1 = EntryPlate1.Text.ToString(),
Plate2 = EntryPlate2.Text.ToString()
};
string restName = "Rest1";
await firebaseClient.Child("Menus/" + restName).PutAsync(databaserecord); //Adicionar reload à página 2 após o click no botão de adicionar ou noutro click
EntryPlate1.Text = "";
EntryPlate2.Text = "";
MyDatabaseRecord.cs:
public class MyDatabaseRecord
{
public string Plate1 { get; set; }
public string Plate2 { get; set; }
}
What I mean by "it deletes the unaltered ones" is that, in this example, although my only changes are to "Plate1" and "Plate2" values, when its executed, it deletes "Plate3" from the database, instead of just replacing the ones I'm targeting.
What can I change to my code in order for this to work like intended?

The PutAsync method is the equivalent of a HTTP PUT call of the Firebase REST API, which rewrites the data at the given path with the data that you pass into the call. If you want to instead patch the data, use PatchAsync which performs a selective update only overwriting the properties that you pass in.

Related

How to use variable static list when multi user access

this variable works fine if used by one user, but when used by two or more users then the "static" variable will be read by the next user, the first user instance when filling the gridview there are 5 rows of data and I try to access through other browser when entering the page, gridview on the second user already filled 5 rows of data in input by the first user. then how the solution to this problem? please see my code and give me an solutions. thanks.
static List<ServicesModels> _gridPackageDetail = new List<ServicesModels>();
private void AddListAction(string alfa, string beta)
{
ServicesModels data = new ServicesModels()
{
id_service_detail = Guid.NewGuid(),
scope_name = alfa,
detail_name= beta
};
_gridPackageDetail.Add(data);
}
public ActionResult GridPackageDetail()
{
ViewBag.DataListPackage = _gridPackageDetail.OrderBy(a => a.scope_name).ToList();
return PartialView();
}
my code in mvc3 controller.
The code is working fine, because this is what intended by "static", to have the same data for multi users. In your case you need to create a list or dictionary or multi-dimensional array (any data structure you are comfortABLE with) and save the data per use in it, and then retrieve the data when needed based on the user id.
static List<ServicesModels> _gridPackageDetail = new List<ServicesModels>();
private void AddListAction(string alfa, string beta)
{
ServicesModels data = new ServicesModels()
{
id_service_detail = Guid.NewGuid(),
scope_name = alfa,
detail_name= beta,
user_id = getTheID()// Get the id of the user
};
_gridPackageDetail.Add(data);
}
public ActionResult GridPackageDetail()
{
ViewBag.DataListPackage = _gridPackageDetail.OrderBy(a => a.scope_name && user_id ==getTheID()).ToList();
return PartialView();
}
replace getTheID() by your way of getting the id of the user.
This is used if you want to keep the data of all users. else you should remove the static keyword.

Appending chat history and insert it into the same file

I have a case that I need to log the chat history (I am capable of doing this already) and I need it to be logged in a text file (able to log it already).
The problem is the file is being accessed all over again so I need to somewhere store the filename of the file somewhere else, right now I have this code:
public async Task LogAsync(IActivity activity)
{
var conversation = "";
var convActivity = "";
var ctr = 0;
conversation = $"From: {activity.From.Name}\r\n To: {activity.Recipient.Name}\r\n Message: {activity.AsMessageActivity()?.Attachments}\r\n ";
fileName = "test";
await LogActivity(fileName, conversation);
}
The LogActivity is the one handling the append of the file. So what I need is I want the unique fileName to be instantiated once while appending the file all over again or rather while continuously accessing this method.
Or is there a way to log the chat history of bot once like if a Context.Done was called or before it?
Or the inefficient way I am thinking of was making use of .From.Name and .Recipient.Name
So the result will be:
if (activity.From.Name.ToLower().ToString() == "user")
{
name.Value = $"{activity.From.Name.ToString()}";
conversation = $"From: {activity.From.Name}\r\n To: {activity.Recipient.Name}\n Message: {activity.AsMessageActivity()?.Text}\n";
}
else
{
name.Value = $"{activity.Recipient.Name.ToString()}";
conversation = $"From: {activity.From.Name}\r\n To: {activity.Recipient.Name}\r\n Message: {activity.AsMessageActivity()?.Text}\r\n ";
}
await LogActivity(name.Value, conversation);
If I understand correctly, you just want to persist a value throughout a conversation; in this case a filename.
If that's correct, then you can store it in PrivateConversationData which lives in thecontext.
For example:
context.PrivateConversationData.SetValue<string>("log_filename", "log-name-here.txt");
For an example, check here: https://www.robinosborne.co.uk/2016/08/08/persisting-data-within-a-conversation-with-botframeworks-dialogs/
For a full example about persisting the whole conversation, this might also help: https://www.robinosborne.co.uk/2016/11/22/transcribing-messages-in-botframework/
Okay, rposbo's answer also works if you have your own logger (that's what I observed, or maybe if you can implement it the other way around, you can use it, it's up to you) that will persist on each every conversation you have with your bot, see the link he provided on how to persist the whole conversation. As for my end, I used dictionary to store the filename. So down below is what I did
public string _Name { get { return name; } }
string name;
public static Dictionary<string, string> fileName = new Dictionary<string, string>();
public void SetFileName(string _fileName)
{
var isCached = fileName.TryGetValue("filename", out name);
if (!isCached)
{
name = $"{_fileName}_{DateTime.Now.Ticks}";
fileName.Add("filename", name);
}
}
Btw, can I accept two answers? since rposbo's answer also works, but it just doesn't fit for me.

IsolatedStorage and navigation

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

Entity Framework Add Performance Degrades With More Rows

I'll begin this post by noting that I'm entirely new to the .NET world. ASP, EntityFramework, Linq, etc. are all mostly unknown magic at this point.
Having said that, I've built myself a neat Web API chat-like application with SignalR support for real-time events. It works quite well, but I'm having some performance problems with the Add function.
In my chat application, there are "Pads" (chat rooms) which contain a number of "Mates" and "Messages". Here's my Pad model for reference:
public class Pad
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid PadId { get; set; }
public string StreetAddress { get; set; }
public int ZipCode { get; set; }
public virtual ICollection<Mate> Mates { get; set; }
public virtual ICollection<Message> Messages { get; set; }
}
My problem lies in my SignalR hub that processes a new Message sent to a particular pad. These two lines take about half a second to process.
pad.Messages.Add(msg); // pad is the Pad entity already fetched from the db context
db.Messages.Add(msg);
But they only take that long when Pad.Messages contains a large number of messages. Thousands. If I am sending to a pad with few to no messages, it executes almost instantly.
My initial 'trick' to improve the perceived performance here is to move the adding functions to after I send the notification back to the clients, but I realize something like this could present a potential problem later when there are tens or hundreds of thousands of messages in one pad.
Any advice here would be greatly appreciated!
Here is the entire message send method for reference:
public void SendMessage(string pad_id, string body)
{
var user_id = IdentityExtensions.GetUserId(Context.User.Identity);
body = body.Trim();
if (body.Length <= 0)
{
return;
}
// Check that the user belongs in this pad...
var user = (from u in db.Users
where u.Id == user_id
select u).First();
var pad = (from p in user.Pads where p.PadId == new Guid(pad_id) select p).FirstOrDefault();
if (pad != null) {
// Save the message to the database
var msg = new Message()
{
MessageId = new Guid(),
Author = user,
Body = body,
SendTime = DateTimeOffset.UtcNow,
Pad = pad
};
pad.Messages.Add(msg); // These two lines
db.Messages.Add(msg); // Are the culprit.
db.SaveChangesAsync();
Clients.Group(pad_id).messageReceived(user.Id, pad_id, body, DateTimeOffset.UtcNow); // Send message to clients
}
}
EDIT: I'm on EF 6.0.0
From your code, all you want to do is add 1 row (Message) to the table.
While constructing the Message entity, just use the padid instead of the Pad object.
That way you don't need to deal with all the pad objects. From a DB perspective, you just need to add a Message row with a PadId key.
var msg = new Message()
{
MessageId = new Guid(),
Author = user,
Body = body,
SendTime = DateTimeOffset.UtcNow,
PadId = new Guid(pad_id)
};
// pad.Messages.Add(msg); // don't need this.
db.Messages.Add(msg);
The above should always insert one row and not depend on the number of messages in the pad.
If it still gives a performance problem, then adding a single row is causing a lot of index updates to your table.

List being emptied on submit

I have a C# application where I need the list to "remember" what has been previously entered in it.
http://oi40.tinypic.com/2ivhcuw.jpg
So once the attendee has been added, the previous attendee will stay in the list if a new one is added. Currently it just displays the most recent attendee, I want them to save, until I decide to clear them (maybe in a session?)
List<Information> infoList = new List<Information>();
Information data = new Information();
firstName = resultEntry.Properties["givenname"].Value.ToString();
lastName = resultEntry.Properties["sn"].Value.ToString();
fullName = firstName + " " + lastName;
//data.CWID = resultEntry.Properties["username"].Value.ToString();
data.FullName = fullName;
// data.Email = resultEntry.Properties["email"].Value.ToString();
infoList.Add(data);
For storing items into a session:
Session["MyInformation"] = data;
receiving data out of a session
List<information> data = (List<information>)Session["MyInformation"];
But beware: Sessions ought to be forgotten.
One might consider viewstate but beware here to: viewstates do make a page slow. (easy testings in how big a html page gets when viewstate is added)
one last option might be to include cookies for getting a longer hold on the items.
Write a cookie: http://msdn.microsoft.com/en-us/library/78c837bd(v=vs.100).aspx
Read a cookie : http://msdn.microsoft.com/en-us/library/bd70eh18(v=vs.100).aspx
another option is to hold the data in database => this however means more traffic.
(also a small hint on the sessions, place them in a seperate static class so you can get them through the whole project instead of one page
public static class MySessions
{
public static List<Information> MyData
{
get{
//EDIT in the GET
if(HttpContext.Current.Session["MyInformation"] != null)
return (List<information>)HttpContext.Current.Session["MyInformation"];
else
{
HttpContext.Current.Session["MyInformation"] = new List<Information>();
return new List<Information>();
}
}
set{HttpContext.Current.Session["MyInformation"] = value;}
}
}
EDIT:
use the class as follows: (it's a static class, by entering the classname followed by the property, you can call for it instead of first instantiating the class.
//Set the value from Somewhere
MySessions.MyData = new List<Information>();
//get the values from somewhere
var myInfo = MySessions.MyData;
Depending on the length of the duration of "saving":
Use ViewState - if you want the list to be empty on a page load (not postback). (i.e. ViewState["data"] = infoList)
Use Session - if you want to manually empty the list based on some condition.

Categories

Resources