Saving random number value after site is refreshed - c#

Hey I created a database with question. every question has a unique id (.ID) and a random generator randomly picks numbers and the the question with this number (id) is chosen and appears on the website.
So far so good but I want every question to appear a single time. Sadly every user request is unique so the values aren't remembered.
Is there an easy way to implement this to my code that my when form is transmitted my website still recognise the previous.
var questions = from m in _context.Question
select m;
var rowsTaken = new HashSet<int>();
Random r = new Random();
int rndRowIndex = r.Next(1, 10);
if (!string.IsNullOrEmpty(QuestionLayer))
{
do
{
questions = questions.Where(x => x.ID == rndRowIndex);
//questions = questions.Where(x => x.Layer == QuestionLayer);
} while (listids.Contains(rndRowIndex));
listids.Add(rndRowIndex);
}

Quick answer about random number generator is no. However, you could keep track of questions answered or displayed by marking them in database. Then when random number is generated check the question associated with that number. If answered/displayed already either generate another number for the next question or using the first number generated look at the next question and the next until and so forth until you find the next unanswered question. When a question is chosen for display mark it in database as having been displayed.
Once all questions answered mark all questions as unanswered.

Storage in the database is a good choice. If you don’t want to modify the database, you can use the session to store the randomly generated value each time.
More details, refer to the following code:
First, enable the session in your starup.cs :
In Configuration method add services.AddSession();
In Configure method add app.UseSession();
Then, in you controller:
//retrieve the session
var str = HttpContext.Session.GetString("mykey");
List<int> listids = str == null ? new List<int>() : JsonConvert.DeserializeObject<List<int>>(str);
var questions = from m in _context.Question
select m;
//If all the questions have occurred, to prevent entering into an endless loop, we need to store the previously stored empty.
if (listids.Count == questions.Count())
{
listids = new List<int>();
}
if (!string.IsNullOrEmpty(QuestionLayer)
{
var rowsTaken = new HashSet<int>();
Random r = new Random();
int rndRowIndex = r.Next(1, 10);
while (listids.Contains(rndRowIndex))
{
rndRowIndex = r.Next(1, 10);
}
questions = questions.Where(x => x.ID == rndRowIndex);
listids.Add(rndRowIndex);
//store new list to session
HttpContext.Session.SetString("mykey", JsonConvert.SerializeObject(listids));
}

Related

How do I store the initial state of a list of objects so that I can compare them to an updated list?

I have a list that is constantly being updated throughout my program. I would like to be able to compare the initial count and final count of my list after every update. The following is just a sample code (the original code is too lengthy) but it sufficiently captures the problem.
class Bot
{
public int ID { get; set; }
}
public class Program
{
public void Main()
{
List<Bot> InitialList = new List<Bot>();
List<Bot> FinalList = new List<Bot>();
for (int i = 0; i < 12345; i++)
{
Bot b = new Bot() {ID = i};
InitialList.Add(b);
}
FinalList = InitialList;
for (int i = 0; i < 12345; i++)
{
Bot b = new Bot() {ID = i};
FinalList.Add(b);
}
Console.Write($"Initial list has {InitialList.Count} bots");
Console.Write($"Final list has {FinalList.Count} bots");
}
}
Output:
Initial list has 24690 bots
Final list has 24690 bots
Expected for both lists to have 12345 bots.
What is correct way to copy the initial list so new set is not simply added to original?
To do what you seem to want to do, you want to copy the list rather than assign a new reference to the same list. So instead of
FinalList = InitialList;
Use
FinalList.AddRange(InitialList);
Basically what you had was two variables both referring to the same list. This way you have two different lists, one with the initial values and one with new values.
That said, you could also just store the count if that's all you want to do.
int initialCount = InitialList.Count;
FinalList = InitialList;
Although there's now no longer a reason to copy from one to the other if you already have the data you need.
I get the feeling you actually want to do more than what's stated in the question though, so the correct approach may change depending on what you actually want to do.

Comparing two lists to see if I need to update the database or even add to

I have a simple class which holds a primary key of which I don't know what type it will be before it runs, as i'm getting the data from COM. It will either be an int or string.
I basically just need to fill up my toUpdateList & toAddList. This was working fine below with not too many records to play around with. However now the mongoDBList returns around 65k records and it's all turned very slow and it's taking 15+ minutes to resolve toUpdateList.
I'm pretty new to C# so I'm likely missing something.
I basically just need to compare one list to another and see if the RecordRevision is higher in the toUpdateList. For the toAddList this ones pretty simple as if it doesn't exist it needs to be added.
Thanks for looking I appreciate it!
class KeyRevision
{
public dynamic RecordRevision;
public dynamic PrimaryKey;
}
List<KeyRevision> potentialUpdateList = new List<KeyRevision>();
List<KeyRevision> mongoDBList = new List<KeyRevision>();
List<KeyRevision> toUpdateList = new List<KeyRevision>();
List<KeyRevision> toAddList = new List<KeyRevision>();
var sql = env.ExecuteSQL(sqlQuery);
sql.First();
// Loop over them and add to array
do
{
if (sql.RecordCount > 0)
{
//Console.WriteLine(sql.GetPropertyValue(primaryKey).ToString() + " : " + sql.RecordRevision);
var o = new KeyRevision();
o.PrimaryKey = sql.GetPropertyValue(primaryKey);
o.RecordRevision = sql.RecordRevision;
potentialUpdateList.Add(o);
}
sql.Next();
} while (!sql.EOF);
// Ask mongo for docs
var docs = collection1.Find(_ => true).Project("{RecordRevision: 1}").ToList();
// Get them into our type
mongoDBList = docs.ConvertAll(x => new KeyRevision()
{
PrimaryKey = x.GetValue("_id"),
RecordRevision = x.GetValue("RecordRevision")
});
// Finds which records we need to update
toUpdateList = potentialUpdateList.Where(x =>
mongoDBList.Any(y => y.PrimaryKey == x.PrimaryKey && y.RecordRevision < x.RecordRevision)).ToList();
// Finds the records we need to add
toAddList = potentialUpdateList.Where(x =>
mongoDBList.FindIndex(y => y.PrimaryKey == x.PrimaryKey) < 0).ToList();
Console.WriteLine($"{toUpdateList.Count} need to be updated");
Console.WriteLine($"{toAddList.Count} need to be updated");

Generating random collection from the database

I have the method below in a webapi that pulls data.
I am building an app which will have a listview with default data coming from this method.
I want this data to be changing each time any user starts the app.
How can I generate random data with this method. There are about 4 different categories.
public IEnumerable<ArticlesDto> Find(string category)
{
IEnumerable<ArticlesDto> objArticles = null;
var context = new ArticlesContext();
objArticles = (from j in context.Information
where j.Category == category
select new ArticlesDto()
{
Id = j.Id,
Headlines = j.Headlines,
Url = j.Url,
Category = j.Category,
Summary = j.Summary
});
return objArticles;
}
Example: first time I use the app, I see a list of data about 20 rows(default data).
Second time I use it, I see a different list of another 20 rows different from the last time I used the app.
Why don't you try using AutoFixture. This framework would help you generate random data every time your WebAPI call is made. Here the GITHub link. Please mark as answer if this helps.
https://github.com/AutoFixture
Just OrderBy a random number and then take as many as you like:
Random rnd = new Random();
objArticles = context.Information.Where(i=> i.Category == category)
.OrderBy(i=> rnd.Next())
.Select(i=> new ArticlesDto
{
Id = i.Id,
Headlines = i.Headlines,
Url = i.Url,
Category = i.Category,
Summary = i.Summary
}).Take(20);

Random row from Linq to Sql with no duplicate

What is the best (and fastest) way to retreive random rows using Linq to SQL with unique data / no duplicate record? oh i preffer to do it in 1 statement, does it possible?
i found this relevant question but i don't think that this approach resulting unique records.
i have tried this so far :
//first approach
AirAsiaDataContext LinqDataCtx = new AirAsiaDataContext();
var tes = (from u in LinqDataCtx.users.AsEnumerable()
orderby Guid.NewGuid()
select u).Take(5);
//second approach
var usr = from u in LinqDataCtx.users
select u;
int count = usr.Count(); // 1st round-trip
int index = new Random().Next(count);
List<user> tes2 = new List<user>();
for (int i = 0; i < 5; i++)
{
tes2.Add(usr.Skip(index).FirstOrDefault()); // 2nd round-trip
}
as you can see above, i have tried 2 solution, it works, but above codes did not resulting unique records, there are chances for duplicate.
db.TableName.OrderBy(x=>Guid.NewGuid()).FirstOrDefault();
If you want to take unique data / no duplicate record,
you'd better to use another list to store the row which you taked already.

Why am I getting index out of bounds error from database

I know what index out of bounds is all about. When I debug I see why as well. basically what is happening is I do a filter on my database to look for records that are potential/pending. I then gather a array of those numbers send them off to another server to check to see if those numbers have been upgraded to a sale. If it has been upgraded to a sale the server responds back with the new Sales Order ID and my old Pending Sales Order ID (SourceID). I then do a for loop on that list to filter it down that specific SourceID and update the SourceID to be the Sales Order ID and change a couple of other values. Problem is is that when I use that filter on the very first one it throws a index out of bounds error. I check the results returned by the filter and it says 0. Which i find kind of strange because I took the sales order number from the list so it should be there. So i dont know what the deal is. Here is the code in question that throws the error. And it doesn't do it all the time. Like I just ran the code this morning and it didn't throw the error. But last night it did before I went home.
filter.RowFilter = string.Format("Stage = '{0}'", Potential.PotentialSale);
if (filter.Count > 0)
{
var Soids = new int[filter.Count];
Console.Write("Searching for Soids - (");
for (int i = 0; i < filter.Count; i++)
{
Console.Write(filter[i][1].ToString() + ",");
Soids[i] = (int)filter[i][1];
}
Console.WriteLine(")");
var pendingRecords = Server.GetSoldRecords(Soids);
var updateRecords = new NameValueCollection();
for (int i = 0; i < pendingRecords.Length; i++)
{
filter.RowFilter = "Soid = " + pendingRecords[i][1];
filter[0].Row["Soid"] = pendingRecords[i][0];
filter[0].Row["SourceId"] = pendingRecords[i][1];
filter[0].Row["Stage"] = Potential.ClosedWon;
var potentialXML = Potential.GetUpdatePotentialXML(filter[0].Row["Soid"].ToString(), filter[0].Row["Stage"].ToString());
updateRecords.Add(filter[0].Row["ZohoID"].ToString(), potentialXML);
}
if i'm counting right line 17 is the error where the error is thrown. pendingRecords is a object[][] array. pendingRecords[i] is the individual records. pendingRecords[i][0] is the new Sales OrderID (SOID) and pendingRecords[i][1] is the old SOID (now the SourceID)
Any help on this one? is it because i'm changing the SOID to the new SOID, and the filter auto updates itself? I just don't know
Well I ended up changing how it worked all together and it actually sorts it a bit nicer now. The code i am about to post has a bunch of hard coded numbers due to the structure of my table that is returned. Sorry about that. I have learned since then to not do that, but i am working on a different project now and will change that when I have to change the program. But here is the solution.
var potentials = Server.GetNewPotentials(); //loads all records from server
for (int i = 0; i < potentials.Length; i++)
{
var filter = AllPotentials.DefaultView;
var result1 = CheckSoidOrSource(potentials[i].Soid, true);
var result2 = CheckSoidOrSource(potentials[i].SourceID,false) ;
//This potential can't be found at all so let's add it to our table
if (result1+result2==0)
{
Logger.WriteLine("Found new record. Adding it to DataTable and sending it to Zoho");
AllPotentials.Add(potentials[i]);
filter.RowFilter = string.Format("Soid = '{0}'", potentials[i].SourceID);
var index = AllPotentials.Rows.IndexOf(filter[0].Row);
ZohoPoster posterInsert = new ZohoPoster(Zoho.Fields.Potentials, Zoho.Calls.insertRecords);
AllPotentials.Rows[index]["ZohoID"] = posterInsert.PostNewPotentialRecord(3, filter[0].Row);
}
//This potential is not found, but has a SourceId that matches a Soid of another record.
if (result1==0 && result2 == 1)
{
Logger.WriteLine("Found a record that needs to be updated on Zoho");
ZohoPoster posterUpdate = new ZohoPoster(Zoho.Fields.Potentials, Zoho.Calls.updateRecords);
filter.RowFilter = string.Format("Soid = '{0}'", potentials[i].SourceID);
var index = AllPotentials.Rows.IndexOf(filter[0].Row);
AllPotentials.Rows[index]["Soid"] = potentials[i].Soid;
AllPotentials.Rows[index]["SourceId"] = potentials[i].SourceID;
AllPotentials.Rows[index]["PotentialStage"] = potentials[i].PotentialStage;
AllPotentials.Rows[index]["UpdateRecord"] = true;
AllPotentials.Rows[index]["Amount"] = potentials[i].Amount;
AllPotentials.Rows[index]["ZohoID"] = posterUpdate.UpdatePotentialRecord(3, filter[0].Row);
}
}
AllPotentials.AcceptChanges();
}
private int CheckSoidOrSource(string Soid, bool checkSource)
{
var filter = AllPotentials.DefaultView;
if (checkSource)
filter.RowFilter = string.Format("Soid = '{0}' OR SourceId = '{1}'",Soid, Soid);
else
filter.RowFilter = string.Format("Soid = '{0}'", Soid);
return filter.Count;
}
basically what is happening is that i noticed something about my data when I filter it this way. The two results would only return the following results (0,0) (0,1) and (1,0) (0,0) means that the record doesn't exist at all in this table so I need to add it. (1,0) means that the Sales Order ID (Soid) matches another Soid in the table so it already exists. Lastly (0,1) means that the Soid doesn't exist in this table but i found a record that has the Soid as it's source...which to me means that the one that had it as a source has been upgraded from a potential to a sale, which in turn means i have to update the record and Zoho. This worked out to much less work for me because now I don't have to search for won and lost records, i only have to search for lost records. less code same results is always a good thing :)

Categories

Resources