I get an exception
The specified table does not exist [Limits]
while I'm trying saving new item
(App.Current as App).context.Limits.InsertOnSubmit(new Limit() { Date = DateTime.Now, Value = inputLimit });//this works
(App.Current as App).context.SubmitChanges();//here I get exception
Also I get an error on this line:
var currentLimit = (App.Current as App).context.Limits.Where(l => l.Date.Date == DateTime.Now.Date).FirstOrDefault();
Here is a "model"
public class CalCounterContext:DataContext
{
public CalCounterContext(string connstring):base(connstring)
{
}
public Table<Limit> Limits;
public Table<Meal> Meals;
}
[Table]
public class Limit
{
[Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "Int NOT NULL IDENTITY", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
public int Id { get; set; }
[Column]
public DateTime Date { get; set; }
[Column]
public int Value { get; set; }
}
Sometimes it works, sometimes, doesn't. What could be a reson of my problem?
This normally happens when you add a table in a later version of the database then what is being used. When you create your database context, check to see if it is up to date, and if not, update the database using the DatabaseSchemaUpdater class as described here. If it is just while you are creating the app, uninstall and re-install the app.
Also, I ran into a strange issue where intermittently I would get this error even once the app was in production without any reasoning. Often is occured when I would launch the app and then hit the home or back button to end it quickly. I ended up re-implementing the GetTable<> function used to instantiate my ITable variable in a base database class so that it would do a hard check to see if the table actually existed:
public Table<TEntity> VerifyTable<TEntity>() where TEntity : class
{
var table = GetTable<TEntity>();
try
{
// can call any function against the table to verify it exists
table.Any();
}
catch (DbException exception)
{
if (exception.Message.StartsWith("The specified table does not exist."))
{
var databaseSchemaUpdater = this.CreateDatabaseSchemaUpdater();
databaseSchemaUpdater.AddTable<TEntity>();
databaseSchemaUpdater.Execute();
}
else
{
throw;
}
}
return table;
}
I had the same intermittent error you had. Try removing the database from the device and installing the app again. I found my issue was being caused because I was making changes to the model and when I re-ran the app, I would get this error.
Related
I am following instructions to add a Customized page but cannot get any values to populate the PrimaryView property.
I've followed these steps a few times along with Clean/Build project and closing Visual Studio, but nothing is working. I'm just missing something.
In this order:
1- Created new table in Sql called INMerchandiseGroup with similar makeup as Country table.
2- Defined my graph by creating a PXGraph called MerchandiseGroupMaint.
3- Created axpx page called IN201000 using a ListView control.
4- Bind graph to aspx page by setting datasource TypeName to graph.
5- Generated Data Class through aspx page datasource control, loading new table INMerchandiseGroup, selecting GroupCD and description; set GroupCD IsKey = true and removed string defaults (""), saved and rebuild
6- Added PXSelect actions (alone and with PXDelete, PXCancel) in graph.
7- !!!Problem!!! I go to Properties for datasource to set PrimaryView and nothing is there to select.
Graph:
public class MerchandiseGroupMaint : PXGraph<MerchandiseGroupMaint>
{
PXCancel<INMerchGroup> Cancel;
PXSave<INMerchGroup> Save;
PXSelect<INMerchGroup> MerchandiseGroups;
}
Dataclass:
[System.SerializableAttribute()]
public class INMerchGroup : PX.Data.IBqlTable
{
#region GroupCD
public abstract class groupCD : PX.Data.IBqlField
{
}
protected string _GroupCD;
[PXDBString(10, IsUnicode = true, IsKey = true)]
[PXDefault]
[PXUIField(DisplayName = "Group ID")]
public virtual string GroupCD
{
get
{
return this._GroupCD;
}
set
{
this._GroupCD = value;
}
}
#endregion
#region Description
public abstract class description : PX.Data.IBqlField
{
}
protected string _Description;
[PXDBString(256, IsUnicode = true)]
[PXDefault]
[PXUIField(DisplayName = "Description")]
public virtual string Description
{
get
{
return this._Description;
}
set
{
this._Description = value;
}
}
#endregion
I don't get any error messages...if i manually add the PrimaryView to aspx Source code I get an error that view isn't found.
What am I not doing?
A new screen can be configured this way,look maybe missed something
To Create a Custom Form Template
The problem was so silly, I don't know how i didn't see it. I was missing the "public" access modifier.
public class MerchandiseGroupMaint : PXGraph<MerchandiseGroupMaint>
{
public PXCancel<INMerchGroup> Cancel;
public PXSave<INMerchGroup> Save;
public PXSelect<INMerchGroup> MerchandiseGroups;
}
I have a table that was created with this C# code:
public class ViewHistory
{
[PrimaryKey]
public string YYMMDD { get; set; }
public int UtcNow { get; set; }
public int Assign { get; set; }
public int Learn { get; set; }
public int Practice { get; set; }
public int Quiz { get; set; }
}
and then
db2.CreateTable<ViewHistory>();
I would like to check if the Assign column exists and then remove the Assign column if it exists. So far the suggestions I have seen have all been either quite old or have suggested creating a new table and also don't include any check to see if it exists.
Now with the latest release of sqlite-net-pcl (1.5.2) is there any way I can drop a column? If not can someone recommend a way to do this that's just using the C# features that are available to me with the PCL or with SQL that I could execute.
I saw this on SO but it doesn't really help me:
Delete column from SQLite table
SQLite does not support ALTER TABLE x DROP COLUMN x so you need to create a new table and copy data.
You can do all this via a single multi-line SQL statement and execute it, but this will walk you though the steps using the ORM as much as possible:
Note: This assumes that your model has be updated and does not include that column anymore and your current database might or might not have it...
var conn = new SQLiteConnection(.....
conn.CreateTable<ViewHistory>();
~~~
if (0 < conn.ExecuteScalar<int>("SELECT COUNT(*) AS colcount FROM pragma_table_info('ViewHistory') WHERE name='Assign'"))
{
try
{
conn.BeginTransaction();
conn.Execute("ALTER TABLE ViewHistory RENAME TO backup;");
conn.CreateTable<ViewHistory>();
// Column map and copy data
var columns = conn.GetMapping<ViewHistory>(CreateFlags.None).Columns;
var columnNames = string.Join(",", columns.Select(p => p.Name));
conn.Execute($"INSERT INTO ViewHistory ({columnNames}) SELECT {columnNames} FROM backup;");
conn.Execute("DROP TABLE backup;");
conn.Commit();
conn.Execute("VACUUM");
}
catch (Exception ex)
{
conn.Rollback();
throw ex;
}
}
Note: Typically I just use "DB Browser for SQLite", make all the table/column alterations to the database and copy the "DB Log output" that contains all the SQL statements and paste that into a single SQLConnnection.Exceute statement...
We have two models Person and Address. We have created one combined model of these two models as shown below.
public class Trust_Person_Master
{
public Person_Master PersonMaster { get; set; }
public Address_Master AddressMaster { get; set; }
public Trust_Person_Master()
{
}
public Trust_Person_Master(Person_Master personMaster, Address_Master addressMaster)
{
PersonMaster = personMaster;
AddressMaster = addressMaster;
}
}
Now, we use this Trust_Person_Master model, to save person and address.
So following is the method to save and edit.
[HttpPost, Ajax(true)]
public JsonResult SaveTrust(Trust_Person_Master entity)
{
int nCurrPersonId = entity.PersonMaster.Person_ID;
if (entity.PersonMaster.Person_ID > 0)
{
var update = db.Person.Find(entity.PersonMaster.Person_ID);
if (ModelState.IsValid)
{
TryUpdateModel(update);
}
}
else
{
db.Person.Add(entity.PersonMaster);
}
db.SaveChanges();
HttpContext.Application["TrustPersonSearch"] = null;
return Json(new { person_id = entity.PersonMaster.Person_ID, location_id = entity.PersonMaster.Location_ID });
}
But my problem is that when I edit person, i.e. just field of person master say first name, then that it executes the code as required without giving any error. But does not reflect the changes.
You need to show the TryUpdateModel() method. How are you updating the model ?
By looking at the code you have posted everything seems ok and should not give any problems, however I would like to see the way you are updating your entity, the problem seems to lie there.
Debug as much as possible and come back here with your findings.
Update:
This is now driving me crazy!
After much Googling etc. I am really no closer to a solution.....
However I have found one thing that is puzzling me even more - the "States" of the entities just before the m_dbContext.SaveChanges() call. (see below for full repository code)
var updateInfoState = m_dc.Entry(oldPage.UpdateInfo).State; // State is 'Modified'
var oldPageState = m_dc.Entry(oldPage).State; // State is 'Detached'
this.m_dc.SaveChanges();
Why is "oldPage" detached?
Getting quite desperate now!! ;)
Original:
I appear to be having a problem with EF Code-First updating related tables correctly.
In this simplified example, the 'UpdateInfo' table IS being updated OK with the new DateTime .... but the 'Pages' table is not being updated with the new 'Name' value.
I am seeding code-first POCOs via DropCreateDatabaseAlways / override Seed ... and EF is creating the test tables correctly - so at this point it seems to know what it is doing....
I am sure this is something simple/obvious I am missing!
All help very much appreciated!
My Class definitions:
public class Page
{
public int Id { get; set; }
public string Name { get; set; }
public virtual UpdateInfo UpdateInfo { get; set; } // virtual For Lazy loading
}
[Table("UpdateInfo")] // much better than EF's choice of UpdateInfoes!
public class UpdateInfo
{
public int Id { get; set; }
public DateTime DateUpdated { get; set; }
}
public class DomainContext : DbContext
{
public DbSet<Page> Pages { get; set; }
public DbSet<UpdateInfo> UpdateInfo { get; set; }
}
Tables created by Code-First
Pages Table
===========
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[UpdateInfo_Id] [int] NULL,
UpdateInfo Table
================
[Id] [int] IDENTITY(1,1) NOT NULL,
[DateUpdated] [datetime] NOT NULL,
My Repository code:
public Page Get(int id)
{
Page page = m_dbContext.Pages.Single(p => p.Id == id);
return page;
}
public void Update(PagePostModel model)
{
Page oldPage = Get(model.PageModel.Id); // on oldPage Name = "Hello", DateUpdated = "Last Year"
Page newPage = Mapper.Map<PageModel, Page>(model.PageModel); // on newPage Name = "Goodbye" (AutoMapper)
newPage.UpdateInfo = oldPage.UpdateInfo; // take a copy of the old UpdateInfo since its not contained in the model
newPage.UpdateInfo.DateUpdated = DateTime.UtcNow; // update to now
oldPage = newPage; // copy the updated page we grabbed from dbContext above (NB Everything looks great here..oldPage is as expected)
m_dbContext.SaveChanges(); // update - only the 'UpdateInfo' table is being updated - No change to 'Pages' table :(((
}
As you know, there is a change tracker api in Entity Framework.
To track the changes of your entities you retrieved from the database, DbContext uses its reference value.
Your "Update" function above inserts newPage into oldPage. So, DbContext never knows oldPage is a newPage. So, it is "detached".
However, for UpdateInfo, it is copy of reference in oldPage, so DbContext can track change of that. So, it is "modified".
To solve this problem, how about using the code below?
Page newPage = Mapper.Map<PageModel, Page>(model.PageModel);
oldPage.UpdateInfo = newPage.UpdateInfo;
oldPage.UpdateInfo.DateUpdated = DateTime.UtcNow;
m_dbContext.SaveChanges();
Update
Then, use Attach & Detach methods.
Those methods help you attach and detach entities from DbContext.
Page newPage = Mapper.Map<PageModel, Page>(model.PageModel);
// if you attach first, there will be an exception,
// because there is two entities having same id.
m_dbContext.Entry(oldPage).State = EntityState.Detached;
m_dbContext.Pages.Attach(newPage);
// if you don't set IsModified = true,
// DbContext cannot know it is changed.
m_dbContext.Entry(newPage).State = EntityState.Modified;
m_dbContext.SaveChanges();
The basic problem...
I have a method which executes the following code:
IList<Gig> gigs = GetGigs().WithArtist(artistId).ToList();
The GetGigs() method gets Gigs from my database via LinqToSql...
So, when GetGigs().WithArtist(artistId).ToList() is executed I get the following exception:
Member access 'ListenTo.Shared.DO.Artist Artist' of 'ListenTo.Shared.DO.Act' not legal on type 'System.Collections.Generic.List`1[ListenTo.Shared.DO.Act]
Note that the extension function "WithArtist" looks like this:
public static IQueryable<Gig> WithArtist(this IQueryable<Gig> qry, Guid artistId)
{
return from gig in qry
where gig.Acts.Any(act => (null != act.Artist) && (act.Artist.ID == artistId))
orderby gig.StartDate
select gig;
}
If I replace the GetGigs() method with a method that constructs a collection of gigs in code (rather than from the DB via LinqToSQL) I do NOT get the exception.
So I'm fairly sure the problem is with my LinqToSQl code rather than the object structure.
However, I have NO IDEA why the LinqToSQl version isnt working, so I've included all the associated code below. Any help would be VERY gratefully receivced!!
The LinqToSQL code....
public IQueryable<ListenTo.Shared.DO.Gig> GetGigs()
{
return from g in DBContext.Gigs
let acts = GetActs(g.ID)
join venue in DBContext.Venues on g.VenueID equals venue.ID
select new ListenTo.Shared.DO.Gig
{
ID = g.ID,
Name = g.Name,
Acts = new List<ListenTo.Shared.DO.Act>(acts),
Description = g.Description,
StartDate = g.Date,
EndDate = g.EndDate,
IsDeleted = g.IsDeleted,
Created = g.Created,
TicketPrice = g.TicketPrice,
Venue = new ListenTo.Shared.DO.Venue {
ID = venue.ID,
Name = venue.Name,
Address = venue.Address,
Telephone = venue.Telephone,
URL = venue.Website
}
};
}
IQueryable<ListenTo.Shared.DO.Act> GetActs()
{
return from a in DBContext.Acts
join artist in DBContext.Artists on a.ArtistID equals artist.ID into art
from artist in art.DefaultIfEmpty()
select new ListenTo.Shared.DO.Act
{
ID = a.ID,
Name = a.Name,
Artist = artist == null ? null : new Shared.DO.Artist
{
ID = artist.ID,
Name = artist.Name
},
GigId = a.GigID
};
}
IQueryable<ListenTo.Shared.DO.Act> GetActs(Guid gigId)
{
return GetActs().WithGigID(gigId);
}
I have included the code for the Act, Artist and Gig objects below:
public class Gig : BaseDO
{
#region Accessors
public Venue Venue
{
get;
set;
}
public System.Nullable<DateTime> EndDate
{
get;
set;
}
public DateTime StartDate
{
get;
set;
}
public string Name
{
get;
set;
}
public string Description
{
get;
set;
}
public string TicketPrice
{
get;
set;
}
/// <summary>
/// The Act object does not exist outside the context of the Gig, therefore,
/// the full act object is loaded here.
/// </summary>
public IList<Act> Acts
{
get;
set;
}
#endregion
}
public class Act : BaseDO
{
public Guid GigId { get; set; }
public string Name { get; set; }
public Artist Artist { get; set; }
}
public class Artist : BaseDO
{
public string Name { get; set; }
public string Profile { get; set; }
public DateTime Formed { get; set; }
public Style Style { get; set; }
public Town Town { get; set; }
public string OfficalWebsiteURL { get; set; }
public string ProfileAddress { get; set; }
public string Email { get; set; }
public ImageMetaData ProfileImage { get; set; }
}
public class BaseDO: IDO
{
#region Properties
private Guid _id;
#endregion
#region IDO Members
public Guid ID
{
get
{
return this._id;
}
set
{
this._id = value;
}
}
}
}
I think the problem is the 'let' statement in GetGigs. Using 'let' means that you define a part of the final query separately from the main set to fetch. the problem is that 'let', if it's not a scalar, results in a nested query. Nested queries are not really Linq to sql's strongest point as they're executed deferred as well. In your query, you place the results of the nested query into the projection of the main set to return which is then further appended with linq operators.
When THAT happens, the nested query is buried deeper into the query which will be executed, and this leads to a situation where the nested query isn't in the outer projection of the query to execute and thus has to be merged into the SQL query ran onto the DB. This is not doable, as it's a nested query in a projection nested inside the main sql query and SQL doesn't have a concept like 'nested query in a projection', as you can't fetch a set of elements inside a projection in SQL, only scalars.
I had the same issue and what seemed to do the trick for me was separating out an inline static method call that returned IQueryable<> so that I stored this deferred query into a variable and referenced that.
I think this is a bug in Linq to SQL but at least there is a reasonable workaround. I haven't tested this out yet but my assumption is that this problem may arise only when referencing static methods of a different class within a query expression regardless of whether the return type of that function is IQueryable<>. So maybe it's the class that holds the method that is at the root of the problem. Like I said, I haven't been able to confirm this but it may be worth investigating.
UPDATE: Just in case the solution isn't clear I wanted to point it out in context of the example from the original post.
public IQueryable<ListenTo.Shared.DO.Gig> GetGigs()
{
var acts = GetActs(g.ID); // Don't worry this call is deferred
return from g in DBContext.Gigs
join venue in DBContext.Venues on g.VenueID equals venue.ID
select new ListenTo.Shared.DO.Gig
{
ID = g.ID,
Name = g.Name,
Acts = new List<ListenTo.Shared.DO.Act>(acts),
Description = g.Description,
StartDate = g.Date,
EndDate = g.EndDate,
IsDeleted = g.IsDeleted,
Created = g.Created,
TicketPrice = g.TicketPrice,
Venue = new ListenTo.Shared.DO.Venue {
ID = venue.ID,
Name = venue.Name,
Address = venue.Address,
Telephone = venue.Telephone,
URL = venue.Website
}
};
}
Note that while this should correct the issue at hand there also seems to be another issue in that the deferred acts query is being accessed in each element of the projection which I would guess would cause separate queries to be issued to the database per row in the outer projection.
I don't see anything in your classes to indicate how LINQ to SQL is meant to work out which column is which, etc.
Were you expecting the WithArtist method to be executed in .NET, or converted into SQL? If you expect it to be converted into SQL, you'll need to decorate your Gig class with appropriate LINQ to SQL attributes (or configure your data context some other way). If you want it to be executed in code, just change the first parameter type from IQueryable<Gig> to IEnumerable<Gig>.
I found out that an issue like this (which I also had recently) can be resolved, if you convert the IQueryable (or Table) variable Gigs into a list like so
return from g in DBContext.Gigs.ToList()
...
If that still doesn't work, do the same for all the IQueryables. The reason behind seems to me that some queries are too complex to be translated into SQL. But if you "materialize" it into a list, you can do every kind of query.
Be careful, you should add "filters" (where conditions) early because too much memory consumption can become a problem.