I currently have a firebase project that parses data from the web.
All the data is coming down however I'm wanting to reverse order the results.
I achieve this by doing the following code
public class ExampleItemModel{
public string name;
public string score;
public string level;
public int iconIdx1, iconIdx2, iconIdx3;
}
Then in my fetch data method :-
public void GetDataFromFireBase(string reference, Action<ExampleItemModel[]> onDone){
FirebaseDatabase.DefaultInstance
.GetReference(reference).OrderByChild("score")
.GetValueAsync().ContinueWith(task => {
if (task.IsFaulted) {
// Handle the error...
print("Error: " + task.Exception);
}
else if (task.IsCompleted) {
DataSnapshot snapshot = task.Result;
// Do something with snapshot...
var items = snapshot.Value as Dictionary<string, object>;
int count = items.Count;
var results = new ExampleItemModel[count];
int i = 0;
foreach(var item in items){
results[i] = new ExampleItemModel();
//print("items = " + item);
var values = item.Value as Dictionary<string, object>;
if (reference == "scores"){
print("values count =" + values.Count);
foreach(var value in values){
if(value.Key == "name"){ results[i].name = "" + value.Value;}
if(value.Key == "score"){ print("Score = " + value.Value); results[i].score = "" + value.Value;}
if(value.Key == "level"){ results[i].level = "" + value.Value;}
}
i++;
}
onDone(results);
}
});
}
Ive tried the following : -
in firebase rules I've set
".indexOn":"score",
"score": {
".indexOn": ".value"
}
I've also tried to add the following line of code
results = results.OrderByDescending( x => x.score);
onDone(results);
but I get the following error
severity: 'Error'
message: 'Cannot implicitly convert type 'System.Linq.IOrderedEnumerable' to 'ExampleItemModel[]' [Assembly-CSharp]'
at: '137,14'
source: ''
Would anybody please be able to help
thanks
Thanks Jeff for your response
On the back of this I managed to order the results by doing the following
List <ExampleItemModel> orderedArray = results.OrderByDescending(x => x.score).ToList();
Hope this will help somebody else with this issue in the future
Related
This question already has answers here:
DbUpdateException: Which field is causing "String or binary data would be truncated"
(4 answers)
Closed 12 months ago.
How do you determine which column is the culprit when you have 80(+/-) columns to choose from? Using .Net Core (netcoreapp2.2) and EF Core 2.2.4.
Picked up some existing code and there was an attempt to track columns that failed. However, it does not work. I've looked at dozens of examples here and elsewhere and have not found a way to do this in EF Core 2.x.
public int GetColumnMaxLength(string table, EntityEntry entityEntry)
{
// Just a rough to get the right data - always returns 0 for the moment...
int result = 0;
var modelContext = entityEntry.Context;
var entityType = modelContext.Model.FindEntityType(table); // THIS IS ALWAYS NULL!
if (entityType != null)
{
// Table info
var tableName = entityType.Relational().TableName;
var tableSchema = entityType.Relational().Schema;
// Column info
foreach (var property in entityType.GetProperties())
{
var columnName = property.Relational().ColumnName;
var columnType = property.Relational().ColumnType;
var isFixedLength = property.Relational().IsFixedLength;
};
}
return result;
}
The above code is being called by this catch portion of a try/catch around the db.SaveAsync(); statement.
catch (Exception ex)
{
// -----------------------------------------
// no idea what this was really trying to
// do as it barfs out all columns...
// -----------------------------------------
var dataInfo = new DataInfo();
var strLargeValues = new List<Tuple<int, string, string, string>>();
foreach (var entityEntry in _db.ChangeTracker.Entries().Where(et => et.State != EntityState.Unchanged))
{
// -----------------------------------------
// try to get the column info for all
// columns on this table...
// -----------------------------------------
dataInfo.GetColumnMaxLength("Subscription", entityEntry);
foreach (var entry in entityEntry.CurrentValues.Properties)
{
var value = entry.PropertyInfo.GetValue(entityEntry.Entity);
if (value is string s)
{
strLargeValues.Add(Tuple.Create(s.Length, s, entry.Name, entityEntry.Entity.GetType().Name));
}
}
}
var l = strLargeValues.OrderByDescending(v => v.Item1).ToArray();
foreach (var x in l.Take(100))
{
Trace.WriteLine(x.Item4 + " - " + x.Item3 + " - " + x.Item1 + ": " + x.Item2);
}
throw;
}
So, the crux of the question is: How do I get the SQL column definition from EF Core?
I want to be able to log the specific table and column when incomingData.Length > targetColumnDefinition.Length
FINAL SOLUTION:
public override int SaveChanges()
{
using (LogContext.PushProperty("DbContext:Override:Save", nameof(SaveChanges)))
{
try
{
return base.SaveChanges();
}
catch (Exception ex)
{
var errorMessage = String.Empty;
var token = Environment.NewLine;
foreach (var entityEntry in this.ChangeTracker.Entries().Where(et => et.State != EntityState.Unchanged))
{
foreach (var entry in entityEntry.CurrentValues.Properties)
{
var result = entityEntry.GetDatabaseDefinition(entry.Name);
var value = entry.PropertyInfo.GetValue(entityEntry.Entity);
if (result.IsFixedLength && value.ToLength() > result.MaxLength)
{
errorMessage = $"{errorMessage}{token}ERROR!! <<< {result.TableName}.{result.ColumnName} {result.ColumnType.ToUpper()} :: {entry.Name}({value.ToLength()}) = {value} >>>";
Log.Warning("Cannot save data to SQL column {TableName}.{ColumnName}! Max length is {LengthTarget} and you are trying to save something that is {LengthSource}. Column definition is {ColumnType}"
, result.TableName
, result.ColumnName
, result.MaxLength
, value.ToLength()
, result.ColumnType);
}
}
}
throw new Exception(errorMessage, ex);
}
}
}
On .NET Core 3.1 and EFCore 5.0.2 this logging works with no additional extension methods needed:
try
{
await context.SaveChangesAsync();
}
catch(Exception ex)
{
foreach (var entityEntry in context.ChangeTracker.Entries().Where(et => et.State != EntityState.Unchanged))
{
foreach (var entry in entityEntry.CurrentValues.Properties)
{
var prop = entityEntry.Property(entry.Name).Metadata;
var value = entry.PropertyInfo?.GetValue(entityEntry.Entity);
var valueLength = value?.ToString()?.Length;
var typemapping = prop.GetTypeMapping();
var typeSize = ((Microsoft.EntityFrameworkCore.Storage.RelationalTypeMapping) typemapping).Size;
if (typeSize.HasValue && valueLength > typeSize.Value)
{
Log.Error( $"Truncation will occur: {entityEntry.Metadata.GetTableName()}.{prop.GetColumnName()} {prop.GetColumnType()} :: {entry.Name}({valueLength}) = {value}");
}
}
}
throw ex;
}
As mentioned in the comments, you need the full name and this can be read from the metadata.
public int GetColumnMaxLength(EntityEntry entityEntry)
{
int result = 0;
var table = entityEntry.Metadata.Model.FindEntityType(entityEntry.Metadata.ClrType);
// Column info
foreach (var property in table.GetProperties())
{
var maxLength = property.GetMaxLength();
// For sql info, e.g. ColumnType = nvarchar(255):
var sqlInfo = property.SqlServer();
};
return result;
}
I'm using firebase realtime database for ranking system in my game.
But everytime I try to change the type of value from Datasnapshot's child, it seems to get out of foreach
string cashierChild = "score_cashier";
FirebaseDatabase.DefaultInstance.GetReference("users").OrderByChild(cashierChild).LimitToLast(10)
.GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
Debug.Log("Failed To Load");
}
else if (task.IsCompleted)
{
int rank = 0;
DataSnapshot snapshot = task.Result;
foreach (var item in snapshot.Children)
{
rank = rank + 1;
Debug.Log("Rank: " + rank + ", nickname: " + item.Child("nickname").Value + ", score: " + item.Child(cashierChild).Value);
Debug.Log((int)item.Child(cashierChild).Value);
}
}
});
result of above code
it prints whole ranking definitely really well when I didn't call below code
Debug.Log((int)item.Child(cashierChild).Value);
withoutTheCode
So I though it's because of type casting like (string) or (int)
I resolved the problem using other way for typecasting.
(string)Convert.ChangeType(item.Child("nickname").Value, typeof(string));
I have this c# code where i am trying to get data from a wsdl in visual studio .
The code is okay but when i try to get the data to written on notepad it just shows an empty space :
WindowsService1.ServiceReference1.GetModifiedBookingsOperationResponse getModbkgsResp;
using (var proxy = new WindowsService1.ServiceReference1.InventoryServiceClient())
{
int noofBookings = 1;
getModbkgsResp = proxy.GetModifiedBookings(getModBkgsReq);
WindowsService1.ServiceReference1.Booking[] bookings = new WindowsService1.ServiceReference1.Booking[noofBookings];
getModbkgsResp.Bookings = new WindowsService1.ServiceReference1.Booking[noofBookings];
getModbkgsResp.Bookings = bookings;
if (getModbkgsResp.Bookings != null)
{
for (int i = 0; i < bookings.Length; i++)
{
Booking bk = new WindowsService1.ServiceReference1.Booking();
getModbkgsResp.Bookings[i] = bk;
if (bk != null )
{
bookingSource = bk.BookingSource;
if (bk.BookingId == Bookingcode)
{
this.WriteToFile("Booking Source =" + bookingSource + "");
}
else
{
this.WriteToFile("Sorry could not find your source of booking");
}
}
else
{
this.WriteToFile("Looks like source is null " );
}
}
}
else
{
this.WriteToFile("ERROR: Booking details not returned from GetModifiedBookings! " +StartDate);
}
}
I'm not sure why you are using the new keyword to create items that should have been retrieved from the service. Naturally anything created with new will be initialized with default values and will not contain any data that was retrieved from the service.
My guess is your code should look more like this:
using (var proxy = new WindowsService1.ServiceReference1.InventoryServiceClient())
{
var response = proxy.GetModifiedBookings(getModBkgsReq);
if (response.Bookings == null)
{
this.WriteToFile("ERROR: Booking details not returned from GetModifiedBookings! " +StartDate);
return;
}
var booking = response.Bookings.SingleOrDefault( b => b.BookingId == bookingCode);
if (booking == null)
{
this.WriteToFile("Sorry could not find your source of booking");
return;
}
var bookingSource = booking.BookingSource;
this.WriteToFile("Booking Source =" + bookingSource + "");
}
Hi I am trying to query my Mongo Database by using a list of Facebook ID's as the parameter in order to return the list of users with corresponding accounts. The method works fine in the Unity Editor however when I run it on iOS I get a constructor error (I have set a blank default constructor in order to solve the issue however it still doesn't work)
Initial Method
public void FetchData()
{
//data = Mongo.Instance.players.FindAll().ToList();
if (FB.IsLoggedIn)
{
FB.API("me/friends", HttpMethod.GET, FriendsHighscoreHndlr);
}
}
Callback Method
public void FriendsHighscoreHndlr (IGraphResult FBresult){
var dict = Json.Deserialize(FBresult.ToString()) as Dictionary<string,object>;
var friendList = new List<object>();
friendList = (List<object>)(dict["data"]);
int _friendCount = friendList.Count;
Debug.Log("Found friends on FB, _friendCount ... " +_friendCount);
List<string> friendIDsFromFB = new List<string>();
for (int i=0; i<_friendCount; i++) {
string friendFBID = getDataValueForKey( (Dictionary<string,object>)(friendList[i]), "id");
string friendName = getDataValueForKey( (Dictionary<string,object>)(friendList[i]), "name");
Debug.Log( i +"/" +_friendCount +" " +friendFBID +" " +friendName);
friendIDsFromFB.Add(friendFBID);
}
//friendIDsFromFB.Add(AccessToken.CurrentAccessToken.UserId);
var query = Query.In("facebookID", BsonArray.Create(friendIDsFromFB));
//Debug.Log(query);
data = Mongo.Instance.players.Find(query).ToList();
}
Data Value for Key Method
private string getDataValueForKey(Dictionary<string, object> dict, string key) {
object objectForKey;
if (dict.TryGetValue(key, out objectForKey)) {
return (string)objectForKey;
} else {
return "";
}
}
Return Query Result
{
"_id" : ObjectId("XXXXXX"),
"facebookID" : "XXXXXXXXXXXXXX",
"name" : "John Doe",
"highScore" : 40501
}
Have you tried using a filter from Mongo's .NET drivers?
I would suggest trying something like the example below. (Note: this event is being fired on a pre-defined object which is being defined as a collection.)
var filter = Builders<Object>.Filter.Eq(obj => obj.attribute, List<IDs>);
I am writing a small data migration tools from one big database to another small database. All of the others data migration method worked satisfactorily, but the following method has given an exception from the SKIP VALUE IS 100. I run this console script remotely as well as inside of the source server also. I tried in many different was to find the actual problem what it is. After then I found that only from the SKIP VALUE IS 100 it is not working for any TAKE 1,2,3,4,5 or ....
Dear expertise, I don't have any prior knowledge on that type of problem. Any kind of suggestions or comments is appreciatable to resolve this problem. Thanks for you time.
I know this code is not clean and the method is too long. I just tried solve this by adding some line of extra code. Because the problem solving is my main concern. I just copy past the last edited method.
In shot the problem I can illustrate with this following two line
var temp = queryable.Skip(90).Take(10).ToList(); //no exception
var temp = queryable.Skip(100).Take(10).ToList(); getting exception
private static void ImporterDataMigrateToRmgDb(SourceDBEntities sourceDb, RmgDbContext rmgDb)
{
int skip = 0;
int take = 10;
int count = sourceDb.FormAs.Where(x=> x.FormAStateId == 8).GroupBy(x=> x.ImporterName).Count();
Console.WriteLine("Total Possible Importer: " + count);
for (int i = 0; i < count/take; i++)
{
IOrderedQueryable<FormA> queryable = sourceDb.FormAs.Where(x => x.FormAStateId == 8).OrderBy(x => x.ImporterName);
List<IGrouping<string, FormA>> list;
try
{
list = queryable.Skip(skip).Take(take).GroupBy(x => x.ImporterName).ToList();
//this line is getting timeout exception from the skip value of 100.
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
sourceDb.Dispose();
rmgDb.Dispose();
sourceDb = new SourceDBEntities();
rmgDb = new RmgDbContext();
skip += take;
continue;
}
if (list.Count > 0)
{
foreach (var l in list)
{
List<FormA> formAs = l.ToList();
FormA formA = formAs.FirstOrDefault();
if (formA == null) continue;
Importer importer = formA.ConvertToRmgImporterFromFormA();
Console.WriteLine(formA.FormANo + " " + importer.Name);
var importers = rmgDb.Importers.Where(x => x.Name.ToLower() == importer.Name.ToLower()).ToList();
//bool any = rmgDb.Importers.Any(x => x.Name.ToLower() == formA.ImporterName.ToLower());
if (importers.Count() == 1)
{
foreach (var imp in importers)
{
Importer entity = rmgDb.Importers.Find(imp.Id);
entity.Country = importer.Country;
entity.TotalImportedAmountInUsd = importer.TotalImportedAmountInUsd;
rmgDb.Entry(entity).State = EntityState.Modified;
}
}
else
{
rmgDb.Importers.Add(importer);
}
rmgDb.SaveChanges();
Console.WriteLine(importer.Name);
}
}
skip += take;
}
Console.WriteLine("Importer Data Migration Completed");
}
I have fixed my problem by modifying following code
var queryable =
sourceDb.FormAs.Where(x => x.FormAStateId == 8)
.Select(x => new Adapters.ImporterBindingModel()
{
Id = Guid.NewGuid().ToString(),
Active = true,
Created = DateTime.Now,
CreatedBy = "System",
Modified = DateTime.Now,
ModifiedBy = "System",
Name = x.ImporterName,
Address = x.ImporterAddress,
City = x.City,
ZipCode = x.ZipCode,
CountryId = x.CountryId
})
.OrderBy(x => x.Name);