I am using this function to query a table by its primary ID.
public virtual List<TModel> LoadAllWithChildren()
{
lock(Connection)
{
var result = LoadAll();
foreach (var item in result)
{
try
{
Connection.GetChildren(item);
}
catch (Exception e)
{
DebugTraceListener.Instance.WriteLine(GetType().Name,
"Can not load Child for itemType: " + item.GetType().Name + " reason: " + e);
}
}
return result;
}
}
But this always return results in regards to the primary key. The table I am querying on looks like this:
So when I do this, I get all entries in this table (not just the ones you see in the picture, those are the ones that I want)
So I did a small workaround:
var persistance = await Task.Run(() => PersistenceService.PresentationSequence.LoadAllWithChildren());
List<PresentationSequence> resSequence = new List<PresentationSequence>();
foreach(var elem in persistance)
if (elem.PresentationId == 166)
resSequence.Add(elem);
The result is the list as seen in the picture.
This, however, is slow.
Is there a way to use another SQlite function that will give me the list already filter for "166" in "presentationID"?
(So no local work is done)
EDIT: I have tried using this function:
public virtual TModel LoadById(int id)
{
lock(Connection)
{
try
{
var result = Connection.Get<TModel>(id);
return result;
}
catch (Exception ex)
{
DebugTraceListener.Instance.WriteLine(GetType().Name, $"Cannot find item with ID: {id}\n\n{ex}");
return null;
}
}
}
But this will only take the primary key in. But I want to query for presentation ID and not get a single result from the ID column
I ended up going with the query function:
try
{
var result = Connection.Query<TModel>(querystring);
return result;
}
Related
I have a list in a view with values that need to be updated.
When calling the http method, I am going thru the list components and looking into the database for a item with the right Id and updating the Grade value. My problem is that I can't return the right item from the database, it always returns null. I have checked with debugging, the item from the list with the Id that I am looking for has the right value, but I can't return the item from db.
I have also tried with the sql raw query and it gives me the same error.
This is my code - the var exam is always null :
public ActionResult UpdateExams(ExamsList examList)
{
var examVM = new ExamViewModel
{
Professor = _context.Professor.ToList()
};
examVM.ExamsList = examList;
if (!ModelState.IsValid)
{
var GradesList = new List<int>();
for (int i = 5; i <= 10; i++)
{
GradesList.Add(i);
}
var GradesListSL = new SelectList(GradesList);
return PartialView("ExamsTable", examList);
}
try
{
for (int i = 0; i < examList.ExamDetails.Count; i++)
{
var exam = _context.Exam.Single(e => e.Id == examList.ExamDetails[i].Id);
// var exam = _context.Database.SqlQuery<Exam>(#"SELECT Id as Id,Grade as Grade
//FROM Exam
//WHERE Id={0})
//", examList.ExamDetails[i].Id).ToList();
exam.Grade = examList.ExamDetails[i].Grade == 0 ? exam.Grade : examList.ExamDetails[i].Grade;
}
// _context.SaveChanges();
TempData["InsertingExam"] = "Success!";
// return RedirectToAction("Create", "Exams");
return Json(new { redirectTo = Url.Action("Edit", "Exams") });
}
catch (System.Data.Entity.Infrastructure.DbUpdateException ex) //DbContext
{
string exception = ex.StackTrace + ex.Message;
ModelState.AddModelError("Error", exception);
return View(examVM);
throw;
}
catch (Exception ex)
{
string exception = ex.StackTrace + ex.Message;
ModelState.AddModelError("Error", exception);
return View(examVM);
throw;
}
finally
{
_context.SaveChanges();
}
}
The problem was that I was trying to do the database operation with the view model class.
After I added creating the model class from the view model everything worked just fine.
Following examples are in C#. I am coding for Windows Phone 8.0 using Visual Studio Express 2012 for Windows Phone.
I have a simple database design (two primary tables, and one many-to-many linking table)
Ingredients(IngredientID,IngredientName)
Effects(EffectID,EffectName)
IngredientEffects(IngredientID,EffectID)
so of course to get the foreign keys working I have the standard Entities and Relationships set up in all three tables
This works fine for the following:
- Adding multiple Ingredients
- Adding multiple Effects
- Adding multiple IngredientEffects
- Deleting an Ingredient (and all of it's associated link records)
- Deleting an IngredientEffect record
- Deleting an Effect record... but only if it isn't linked to any Ingredients
When I try to delete an Effect record with multiple Ingredients linked to it, I query for all associated IngredientEffect records then do a DeleteAllOnSubmit(list); SubmitChanges();
This throws multiple "System.InvalidOperationException" with message of "Sequence contains more than one element" is being thrown in the set operation of the Ingredients.FKIngredientEffects Entity Relationship in the IngredientEffects table. I have tried to build a list of UNIQUE records from this list so I know I have no duplicate records in the list being deleted but get the same message.
I understand that this error happens with the Single type queries, but I'm not using any of those. My queries typically run like:
var query = from item in db.IngredientEffects
where item.EffectID == targetEffectID
select item;
I validate that the query is not null, then attempt to populate a list from it, and check if it is not null and has records in it before proceeding with any other work.
I am at a loss as to why I am getting this error. I use the following Entity Relationship statements in the related Table definintions:
Ingredients:
private EntityRef<IngredientEffect> _ingredientEffect;
[Association(Storage = "_ingredientEffect", ThisKey = "IngredientID", OtherKey = "IngredientID", IsUnique = false, Name = "FK_Ingredients_IngredientEffect")]
public IngredientEffect IngredientEffects
{
get { return _ingredientEffect.Entity; }
set
{
try
{
if (value != _ingredientEffect.Entity)
{
NotifyPropertyChanging("IngredientEffects");
_ingredientEffect.Entity = value;
NotifyPropertyChanged("IngredientEffects");
}
}
catch (Exception exc)
{
Debug.WriteLineIf(Debugger.IsAttached, "AlchemistDB.Ingredients.FKIngredientEffects(set) Exception: " + exc.Message);
//throw new Exception("AlchemistDB.Ingredient.FKIngredientEffects(set) failed.", exc);
}
}
}
Effects:
private EntityRef<IngredientEffect> _effectIngredients;
[Association(Storage = "_effectIngredients", ThisKey = "EffectID", OtherKey = "EffectID", IsUnique = false, Name = "FK_Effect_IngredientEffect")]
public IngredientEffect EffectIngredients
{
get { return _effectIngredients.Entity; }
set
{
try
{
NotifyPropertyChanging("EffectIngredients");
_effectIngredients.Entity = value;
NotifyPropertyChanged("EffectIngredients");
}
catch (Exception exc)
{
Debug.WriteLineIf(Debugger.IsAttached, "AlchemistDB.Effect.FKEffectIngredients(set) Exception: " + exc.Message);
//throw new Exception("AlchemistDB.Effect.FKEffectIngredients(set) failed.", exc);
}
}
}
IngredientEffects:
private EntityRef<Ingredient> _ingredients;
[Association(Storage = "_ingredients", ThisKey = "IngredientID", OtherKey = "IngredientID", IsUnique = false, IsForeignKey = true, Name = "FK_Ingredients_IngredientEffect")]
public Ingredient Ingredients
{
get { return this._ingredients.Entity; }
set
{
try
{
if (value != _ingredients.Entity)
{
NotifyPropertyChanging("Ingredients");
this._ingredients.Entity = value;
NotifyPropertyChanged("Ingredients");
}
}
catch (Exception e)
{
Debug.WriteLineIf(Debugger.IsAttached, "AlchemistDB.IngredientEffect.FKIngredients(set) exception:" + e.Message);
throw new Exception("AlchemistDB.IngredientEffect.FKIngredients(set) failed.", e);
}
}
}
private EntityRef<Effect> _effects;
[Association(Storage = "_effects", ThisKey = "EffectID", OtherKey = "EffectID", IsUnique = false, IsForeignKey = true, Name = "FK_Effect_IngredientEffect")]
public Effect Effects
{
get { return this._effects.Entity; }
set
{
try
{
if (value != _effects.Entity)
{
NotifyPropertyChanging("Effects");
this._effects.Entity = value;
NotifyPropertyChanged("Efffects");
}
}
catch (Exception e)
{
Debug.WriteLineIf(Debugger.IsAttached, "AlchemistDB.IngredientEffect.FKEffects(set) exception:" + e.Message);
throw new Exception("AlchemistDB.IngredientEffect.FKEffects(set) failed.", e);
}
}
}
Any assistance provided will be most welcome!
Thanks,
-Mark
If any Foreign Key's set declaration in a many-to-many Table has conditional logic (like:
if (value!=_myprivateproperty)
{
NotifyPropertyChanging("MyPublicPropertyName");
_myprivateproperty = value;
NotifyPropertyChanged("MyPublicPropertyName");
}
it will cause LINQ to throw this exception, each time a record in that table is deleted. Get rid of the conditional and just use:
NotifyPropertyChanging("MyPublicPropertyName");
_myprivateproperty = value;
NotifyPropertyChanged("MyPublicPropertyName");
Still not sure WHY this happens, but to me it appears to be a bug in LINQ-to-SQL itself.
I am trying to save some data to a SQLite3 database. If I do not use async, I can save the data without any problems. As soon as I try to use the following code however, I receive the following error:
{Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.}
From my UI, I invoke the following SyncDomainTablesAsync method:
private readonly IDataCoordinator _coordinator;
public Configuration(IDataCoordinator coordinator)
{
_coordinator = coordinator;
}
public async Task<int> SyncDomainTablesAsync(IProgress<string> progress, CancellationToken ct, DateTime? lastDateSynced=null, string tableName = null)
{
//Determine the different type of sync calls
// 1) Force Resync (Drop/Create Tables and Insert)
// 2) Auto Update
var domainTable = await GetDomainTablesAsync(progress,ct,lastDateSynced, tableName);
var items = domainTable.Items;
int processCount = await Task.Run<int>( async () =>
{
int p = 0;
progress.Report(String.Format("Syncing Configurations..."));
foreach (var item in items)
{
progress.Report(String.Format("Syncing {0} Information",item.Key));
var task = await SyncTableAsync(item.Value); // INVOKED BELOW
if (task) progress.Report(String.Format("Sync'd {0} {1} records", item.Value.Count,item.Key));
if (ct.IsCancellationRequested) goto Cancelled;
p += item.Value.Count;
}
Cancelled:
if (ct.IsCancellationRequested)
{
//Update Last Sync'd Records
progress.Report(String.Format("Canceling Configuration Sync..."));
ct.ThrowIfCancellationRequested();
}
else
progress.Report(String.Format("Syncing Configurations Compleleted"));
return p;
},ct);
return processCount;
}
private async Task<bool> SyncTableAsync(IEnumerable<object> items, bool includeRelationships = false)
{
try
{
//TODO: Replace with SaveObjects method
var i = await Task.Run(() => _coordinator.SaveObjects(items, includeRelationships));
if (i == 0)
return false;
}
catch(Exception ex)
{
return false;
}
return true;
}
The UI invokes the SyncDomainTablesAsync method. I then create a new Task and loop through the items that were returned from the GetDomainTablesAsync method. During each iteration I await until the SyncTableAsync method completes. Within the SyncTableAsync I am calling a SaveObject method inside of a class that implements my IDataCoordinator interface.
public override int SaveObjects(IEnumerable<object> items, Type underlyingType, bool saveRelationships = true)
{
int result = 0;
if (items == null)
throw new ArgumentNullException("Can not save collection of objects. The collection is null.");
else if (items.Count() == 0)
return 0;
// Check if table exists.
foreach (var item in items)
this.CreateTable(item.GetType(), saveRelationships);
using (SQLiteConnection connection = new SQLiteConnection(this.StorageContainerPath))
{
connection.BeginTransaction();
foreach (var item in items)
{
result += ProcessSave(item, saveRelationships, connection);
}
try
{
connection.Commit();
}
catch (SQLiteException ex)
{
connection.Rollback();
throw ex;
}
}
return result;
}
public override int CreateTable(Type type, bool createRelationalTables = false)
{
if (this.TableExists(type) == 1)
return 1;
using (SQLiteConnection cn = new SQLiteConnection(this.StorageContainerPath))
{
try
{
// Check if the Table attribute is used to specify a table name not matching that of the Type.Name property.
// If so, we generate a Sql Statement and create the table based on the attribute name.
//if (Attribute.IsDefined(type, typeof(TableAttribute)))
//{
// TableAttribute attribute = type.GetAttribute<TableAttribute>();
// Strongly typed to SQLiteCoordinator just to get a SqlQuery instance. The CreateCommand method will create a table based on 'type'
var query = new SqlQuery<SQLiteCoordinator>().CreateCommand(DataProviderTypes.Sqlite3, type);
query = query.TrimEnd(';') + ";";
cn.Execute(query);
//}
// Otherwise create the table using the Type.
//else
//{
// cn.CreateTable(type);
//}
// If we are to create relationship tables, we cascade through all relationship properties
// and create tables for them as well.
if (createRelationalTables)
{
this.CreateCascadingTables(type, cn);
}
}
catch (Exception ex)
{
return 0;
}
}
return 1;
}
The flow of the code goes
UI->SyncDomainTablesAsync->SyncTableAsync->SaveObjects->SaveTable(type)
The issue that I have is within Save Table. If I just use SaveTable synchronously I have no issues. Using it in my async method above, causes a thread abort exception. The exception is thrown within the SQLite.cs file included with SQLite.net (within the . The weird thing is that the table is created in the database, even though the exception is thrown. The error is thrown some times when the Prepare() function is called and the rest of the time when the SQLite3.Step() function is called.
public int ExecuteNonQuery ()
{
if (_conn.Trace) {
Debug.WriteLine ("Executing: " + this);
}
var r = SQLite3.Result.OK;
var stmt = Prepare (); // THROWS THE ERRROR
r = SQLite3.Step(stmt); // THROWS THE ERRROR
Finalize(stmt);
if (r == SQLite3.Result.Done) {
int rowsAffected = SQLite3.Changes (_conn.Handle);
return rowsAffected;
} else if (r == SQLite3.Result.Error) {
string msg = SQLite3.GetErrmsg (_conn.Handle);
throw SQLiteException.New (r, msg);
} else {
throw SQLiteException.New (r, r.ToString ());
}
}
I assume that because my foreach statement awaits the return of SyncTableAsync that none of the threads are closed. I am also getting a system transaction critical exception that says "attempting to access a unloaded app domain".
Am I using await/async incorrectly with Sqlite3 or is this an issue with Sqlite3 that I am not aware of.
Attached is a photo of the Parallel's stack and the exception.
EDIT
When I try to run the code above as well in unit tests, the unit tests process never dies. I have to exit Visual Studio in order to get the process to die. I am assuming something in SQLite.dll is grabbing a hold of the process when the exception is thrown and not letting go, but I am not sure.
EDIT 2
I can modify the initial method SyncDomainTablesAsync to the following and the code runs without error. The issue is my use of async and await I believe.
public async Task<int> SyncDomainTablesAsync(IProgress<string> progress, CancellationToken ct, DateTime? lastDateSynced=null, string tableName = null)
{
var domainTable = await GetDomainTablesAsync(progress,ct,lastDateSynced, tableName);
var items = domainTable.Items;
foreach (var item in items)
{
_coordinator.SaveObjects(item.Value, typeof(object), true);
}
return 1;
}
I am using MongoVue application to show the data preview stored in "MongoDb".
In the attached image, the database name "Energy" has collection name "DataLog". In "DataLog", there are several rows. I am adding these row to the collection by reading it from a .CSV file.
Now sometimes the column name Pings has huge data [say array of 2000 items] for a single row due to which the exception occurs i.e if "MaxDocumentSize exceeds in 16MB"
Since the Pings array was huge which threw an exception and to avoid this, I removed the collection of Pings [i.e. entered blank collection] from row and tried to Insert, it went successful.
Now I want to update the Pings for the same entry, but in case the array is something like 2000 elements or above, then I wish to update it in group of 500 items [500 x 4 = 2000] in a loop.
Can anyone help me out.
** SAMPLE CODE **
private void InsertData(Datalog xiDatalog)
{
List<Ping> tempPings = new List<Ping>();
tempPings.AddRange(xiDatalog.Pings);
xiDatalog.Pings.RemoveAll(x => x.RowId != 0);
WriteConcernResult wc = mongoCollection.Insert(xiDatalog);
counter++;
var query = new QueryDocument("_id", xiDatalog.Id);
MongoCursor<Datalog> cursor = mongoCollection.FindAs<Datalog>(query);
foreach (Datalog data in cursor)
{
AddPings(data, tempPings, mongoCollection);
break;
}
}
private void AddPings(Datalog xiDatalog, List<Ping> xiPings, MongoCollection<Datalog> mongoCollection)
{
int groupCnt = 0;
int insertCnt = 0;
foreach (Ping px in xiPings)
{
xiDatalog.Pings.Add(px);
groupCnt++;
if (((int)(groupCnt / 500)) > insertCnt)
{
UpdateDataLog(xiDatalog.Id, xiDatalog.Pings, mongoCollection);
insertCnt++;
}
}
}
private bool UpdateDataLog(BsonValue Id, List<Ping> tempPings, MongoCollection<Datalog> mongoCollection)
{
bool success = false;
try
{
var query = new QueryDocument("_id", Id);
var update = Update<Datalog>.Set(e => e.Pings, tempPings);
mongoCollection.Update(query, update);
success = true;
}
catch (Exception ex)
{
string error = ex.Message;
}
return success;
}
Answer : Just modified the code to use Update.PushAll() instead of Update.Set()
Please refer below code
private bool UpdateDataLog(BsonValue Id, List<Ping> tempPings, MongoCollection<Datalog> mongoCollection)
{
bool success = false;
try
{
var query = new QueryDocument("_id", Id);
var update = Update<Datalog>.PushAll(e => e.Pings, tempPings);
mongoCollection.Update(query, update);
success = true;
}
catch (Exception ex)
{
string error = ex.Message;
}
return success;
}
My issue is the following: i'm trying to build a function to which i could pass a list of items, which would then go to the db with each of those items and update them. I believe the issue is within the way datacontexts are being used but i cannot figure out this issue.
Here is my function that builds the list of items that were changed:
protected void btnSave_Click(object sender, EventArgs e)
{
List<AFF_CMS_FMA> fmasToSave = new List<AFF_CMS_FMA>();
AFF_CMS_FMA newFmaItem = new AFF_CMS_FMA();
foreach (AFF_CMS_FMA fmaItem in FmaLib.fetchAllActiveAssetsInFMA())
{
if (fmaItem.SortOrder != Convert.ToInt32(Request.Form["fmaItem_" + fmaItem.ID + "_SortOrder"]))
{
newFmaItem = fmaItem;
newFmaItem.Name = SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_Name"]);
newFmaItem.AssetID = Convert.ToInt32(Request.Form["fmaItem_" + fmaItem.ID + "_AssetID"]);
newFmaItem.SortOrder = Convert.ToInt32(Request.Form["fmaItem_" + fmaItem.ID + "_SortOrder"]);
newFmaItem.ImagePathEn = SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_ImagePathEn"]);
newFmaItem.ImagePathCh = SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_ImagePathCh"]);
newFmaItem.StartDate = DateTime.Parse(SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_StartDate"]));
newFmaItem.EndDate = DateTime.Parse(SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_EndDate"]));
newFmaItem.ClickToUrl = SecurityLib.SqlSafeString(Request.Form["fmaItem_" + fmaItem.ID + "_ClickToUrl"]);
fmasToSave.Add(newFmaItem);
}
}
FmaLib.saveEditedFmas(fmasToSave);
}
here is the function that the foreach loops calls to get all the items that are in the db:
public static List<AFF_CMS_FMA> fetchAllActiveAssetsInFMA()
{
List<AFF_CMS_FMA> results = null;
using (fmaDataContext db = new fmaDataContext())
{
using (TransactionScope ts = new TransactionScope())
{
try
{
if (HttpContext.Current.Cache["fmaActiveList"] == null)
{
db.LoadOptions = loadAll;
results = clsCompiledQuery.getAllActiveFmas(db).ToList();
HttpContext.Current.Cache["fmaActiveList"] = results;
}
else
results = (List<AFF_CMS_FMA>)HttpContext.Current.Cache["fmaActiveList"];
ts.Complete();
}
catch (Exception ex)
{ Transaction.Current.Rollback(); }
}
return results;
}
}
here are the queries being used:
protected static class clsCompiledQuery
{
public static Func<DataContext, IOrderedQueryable<AFF_CMS_FMA>>
getAllActiveFmas = CompiledQuery.Compile((DataContext db)
=> from fma in db.GetTable<AFF_CMS_FMA>()
where fma.IsArchived == false
orderby fma.SortOrder ascending
select fma);
public static Func<DataContext, int,IQueryable<AFF_CMS_FMA>>
getFmaById = CompiledQuery.Compile((DataContext db, int ID)
=> from fma in db.GetTable<AFF_CMS_FMA>()
where fma.ID == ID
select fma);
}
and finally this were im trying to get the save to happen to the db but no exeptions are throwns, yet the db does not change
public static bool saveEditedFmas(List<AFF_CMS_FMA> fmaToSaveList)
{
using (fmaDataContext db = new fmaDataContext())
{
using (TransactionScope ts = new TransactionScope())
{
try
{
foreach (AFF_CMS_FMA fmaItemToSave in fmaToSaveList)
{
AFF_CMS_FMA fmaItemToUpdate = clsCompiledQuery.getFmaById(db, fmaItemToSave.ID).ToList()[0];
fmaItemToUpdate = fmaItemToSave;
db.SubmitChanges();
}
return true;
}
catch (Exception ex)
{
Transaction.Current.Rollback();
return false;
}
}
}
}
I have checked and the table does contain a primary key in the designer. If i do the save from the btnSave_click function by passing a datacontext to the fetchAllActiveAssetsInFMA() then doing submitchanges on that context it works .. but im trying to abstract that from there.
thanks all in advance
Your not calling ts.Complete in function saveEditedFmas.
Also I would recommend calling db.SubmitChanges(); outside of the for loop. And why do you have a transaction in function fetchAllActiveAssetsInFMA? It's only fetching data right? And I'm not quite sure whats happening inside the for loop in save function, looks strange.
I think you should map the properties from fmaItemToSave to fmaItemToUpdate
foreach (var fmaItemToSave in fmaToSaveList)
{
var fmaItemToUpdate = clsCompiledQuery.getFmaById(db, fmaItemToSave.ID).First();
fmaItemToUpdate.Name = fmaItemToSave.Name;
fmaItemToUpdate.AssetID = fmaItemToSave.AssetID;
//And the rest of the properties
}
db.SubmitChanges();