Wrong select query generated with Entity Framework (mysterious extra column) - c#

I'm playing around trying to get a simple MVC website working. In it I am using a database and Entity Framework to communicate with it (as I have been doing for months on other projects).
Everything has been going fine up until I tried to retrieve from a specific table in my database. If I query that, the select that EF generates mysteriously contains a column that does not exists in that table (or any table in that database). This of course throws an exception complaining about the column not existing:
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.SqlClient.SqlException: Invalid column name 'PerformerFolder_Id'.
I've created a UnitOfWork object that uses the repository pattern to retrieve the data, and to make it as simple as possible, I exposed the DataContext so I could manually query that for testing:
var test = loUnitOfWork.Context.Set<DAL.File>();
The DAL.File is a class generated by the POCO generator:
public partial class File : BaseEntity
{
public int Id { get; set; }
public string FilePath { get; set; }
public string FileName { get; set; }
public virtual ICollection<FilePerformer> FilePerformerCollection { get; set; }
public virtual ICollection<FileProperty> FilePropertyCollection { get; set; }
public File()
{
FilePerformerCollection = new List<FilePerformer>();
FilePropertyCollection = new List<FileProperty>();
InitializePartial();
}
partial void InitializePartial();
}
I do have a PerformerFolder that has an Id column as the primary key, but that is in no way connected to the file table.
If I enable debug logging on the DataContext I see that it runs the following query:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[FilePath] AS [FilePath],
[Extent1].[FileName] AS [FileName],
[Extent1].[PerformerFolder_Id] AS [PerformerFolder_Id]
FROM [dbo].[File] AS [Extent1]
I've tried searching all file for "PerformerFolder" and other than the logical places (in the PerformerFolder class) it did not turn up anything. It seems to be generated based on something, but I just can't figure out what or where.
Does anyone have any suggestions?

Try searching all code files for PerformerFolder without the 'id'
EF adds that to navigation properties on it's own.
as #Giorgi mentioned, it must be a partial class somewhere, or maybe a left over from a previous build ?

Related

Why can't I read a TEXT attribute from SQLITE TABLE in the application?

I this table in a Sqlite db3:
with data in it which I can read with a simple query in SQLite Studio SQL editor:
Select Testo FROM Contenuto
As you can see i only need the Testo attribute.
When I try to do the same query or try to retrive all the attributes (Id, IDSezione, Indice, Testo), in my xamarin Forms Application, the result have all of them but Testo. (Contenuti is a List of Contenuto objects)
This is my DB method:
public Task<List<Contenuto>> GetContenutoAsync(int idsezione)
{
return Database.Table<Contenuto>().Where(i => i.IDSezione == idsezione).ToListAsync();
}
So I'm wondering what is the problem and if someone can help me.
I thought it was a size limit dimension but it do the same with just a character instead of a long text as I need.
class
[Table(nameof(Contenuto))]
public class Contenuto
{
public int ID { get; set; }
public int IDSezione { get; set; }
public int Indice { get; set; }
public string Testo { get; set; }
}
Thanks, Riccardo
So this is how I resolve my problem:
Originally the Testo attribute of the table was named Contenuto as the table name. Not noticing it, I added the DB to the projects anyway.
I noticed that problem on the first run of the app (thrown an exception since you can use the table name as attribute in query), and edited the DB in the common project.
Doing this will not update the Android/iOS DB linked file.
That was the actual problem in my method I was looking for Testo attribute but was not there.
So when you add the DB as new element to android or iOS projects, remember to set its property to Always copy, doing this will always update the linked DB when the app is built.

How do I query a View in SQLite.net?

I am writing a mobile app using Xamarin.Forms PCL in Visual Studio with a local SQLite database. I am using the SQLite.net-PCL Async plugin because sqlite-net-pcl kept crashing my app.
I am able to query tables fine, but I'm not able to figure out how to query views.
How I am successfully querying a table
Model
[Table("pitchers")]
public class Pitcher
{
[PrimaryKey, AutoIncrement, Column("id")]
public ushort Id { get; set; }
[Column("first_name")]
public string FirstName { get; set; }
[Column("last_name")]
public string LastName { get; set; }
[Column("uniform_number")]
public byte UniformNumber { get; set; }
}
Query code
public Task<List<Pitcher>> GetAllPitchersAsync()
{
return dbConn.Table<Pitcher>().OrderBy(i => i.LastName).ToListAsync();
}
I have a view called "joined_pitcher_log" that I am trying to query using the same method. I created a model for it and used the same language (except for order by) to query, but I keep getting the error:
SQLite.Net.SQLiteException: no such table: joined_pitcher_log
Things I tried
1) remove the table attribute from the model I created for the view. There is no view attribute to replace it with.
2) use dbConn.QueryAsync instead of dbConn.Table to query the view directly using SQL.
3) looked for other properties and methods for dbConn. There is nothing related to Views.
How do I query Views?
Update: A workaround if there is no way to query Views
I could also write the SQLite View's query in my code, but then I wouldn't know how to reference multiple models, which is a different issue. I'll take either solution at this point (querying a view or writing a query on multiple tables/models that I'm joining)
The only way to get data from a view is to use SQLite-Net's Query or QueryAsync method. Just create a class to hold the returned data.
db.Query<MyReturnType> ("select * from MyView");
or
await db.QueryAsync<MyReturnType> ("select * from MyView");

Entity Framework Invalid column name when adding property that is not in db table

I had decided that there are just too many things that need to be different on the View Presentation Layer compared to what is actually in the database table.
I have a class of properties in C# that represents the model of my database
HOWEVER I was reading about ViewModels and I can see how they can do the nice things of not displaying containing an unnecessary amount of data that you do not wish to display on your view, and it can also be an important aggregrate of combining multiple models in which you have much more available to you for trickling down to the View.
I simply tried to add a class with a property
public class ExtendedFile
{
public string FileSize { get; set; }
}
Then I figured I could simple add this as another property to my other model class , so I added it
public ExtendedFile ExtendedFile { get; set; }
Then it seems that I can in my controller simply hydrate this
file.ExtendedFile.FileSize = ConvertFileSize(file.size);
So then my View now has
<td>#item.ExtendedFile.FileSize</td>
Well that did not work out .. A controller method had code in it in which a linq query that joins 2 tables freaked out. The error message is:
Invalid column name 'ExtendedFile_FileSize'.
The code that causes the error is:
var query = (
from qtips in dbProd.tblTips
where qtips.id == 30
join files in dbProd.tblFiles on qtips.id.ToString()
equals files.#group select new { qtips, files }).ToList();
Add the attribute as [NotMapped] on the property which is not column of database
Thanks to Stephen while I realize that I "can" do use this other model, I'm just going really against the proper patterns in which what a true ViewModel is for
Thus I already had this working 40 minutes ago by simply adding the [NotMapped]
[NotMapped]
public ExtendedFile ExtendedFile { get; set; }
It exposes a bigger issue of the fact that I was not understanding the ViewModel.
So while that "works" I am going to instead have a ViewModel with
The properties I want to display from the tblFiles class
The properties from this this ExtendedFile class such as
public class ExtendedFile
{
public string FileSize { get; set; }
//more properties
}
This means that it can not find a field of the database that defined in the model.
For example, my problem was that I had written the "Connection string" with the test database wrong.

Entity Framework 5 with Oracle table/view doesn't exist inconsistency?

Any help or advice regarding this issue is greatly appreciated.
I am currently working on a project that requires a change in our data layer from a local MS SQL instance to a hosted Oracle solution.
Previously, we were using Entity Framework (Code-First) to build our data layer. I would like to take the same approach with the new data layer. We have several applications that use this library, so trying to keep the new data layer as close to the same (objects, names, etc.) as the original would be ideal. I know that Code-First is not officially supported by Oracle (a work in progress), but have read where others have had some success. Thus, for these reasons, I am attempting to do the same.
I have created my Oracle EF data layer to match as closely as I can to the original MS SQL EF data layer. The issue that I'm currently having is that when I run a query to retrieve the first or default entity from the data layer, I get the following exception:
Oracle.DataAccess.Client.OracleException: ORA-00942: table or view does not exist
If I use the exact same DbContext instance and instead run a sql query using the DbContext.Database.SqlQuery(sqlString), it works. The reason I mention this is because I've read the "table or view does not exist" error refers to a database permissions issue. That does not appear to be the case this time, since I'm using the exact same connection string in the same connection object. The only difference appears to be in using traditional sql statements versus the DbSet entities (& configurations).
My entities are relatively simple, flat objects.
public class HourlyPrice
{
public DateTime MarketDate { get; set; }
public int HourEnding { get; set; }
public string LocationId { get; set; }
public string LocationName { get; set; }
public decimal? Price { get; set; }
public int IsValid { get; set; }
public DateTime DateInserted { get; set; }
public DateTime? DateUpdated { get; set; }
}
public HourlyPriceConfiguration(string viewName)
{
ToTable(viewName);
HasKey(x => new { x.MarketDate, x.HourEnding, x.LocationName });
Property(x => x.Price).HasPrecision(13, 6);
HasEntitySetName("SourceHourlyPrices");
}
Inside my DbContext, I add the HourlyPriceConfiguration injecting the viewName ...
modelBuilder.Configurations.Add(new HourlyPriceConfiguration(this.viewName));
... and declare my IDbSet as ...
public IDbSet<HourlyPrice> SourceHourlyPrices { get; set; }
When running the code, this works ...
var sql = "select * from " + this.viewName;
var prices = db.Database.SqlQuery<HourlyPrice>(sql);
var price = prices.FirstOrDefault();
... but this ...
var price = db.SourceHourlyPrices.FirstOrDefault();
... produces the "table or view does not exist" error.
Is this just an issue with the Code-First approach, or am I missing something here? When debugging the application, I can see the viewName being passed to the configuration class is the same that is being passed to the sql statement used in SqlQuery. I've tried removing the HasEntitySetName() and changing the IDbSet to the standard HourlyPrices, but that didn't work, either.
Thanks again, in advance.
I would like to confirm that I had the same problem with a table name.
In Oracle if the name is not full UPPER CASE the table/view is not found.
Code First Automatic Migrations is limited to working with the dbo schema only.
https://community.oracle.com/thread/3622163
You can put it in beginning OnModelCreating method of your Context class as a workaround.
if (this.Database.Connection.GetType().Equals(typeof(Oracle.ManagedDataAccess.Client.OracleConnection)))
{
modelBuilder.HasDefaultSchema(new Oracle.ManagedDataAccess.Client.OracleConnectionStringBuilder(this.Database.Connection.ConnectionString).UserID);
}
The ORA-00942 exception is not a permission issue (depends on how you look at it of course); but it means that the table you are querying is not visible to your user.
You may try to explicitly set the name of your schema in your ToTable method call by using the ToTable(tableName, schemaName) implementation and see what happens.
Just wanted to add that I had the same problem after moving the DB to a different schema. I realised that it is critically to have the schema name in upper case when using ToTable(tableName, schemaName).

SubSonic edit class problem

I'm having a very odd issue with SubSonic where when I edit a class the database isn't being updated, even when I delete it and regenerate it.
Example: Simple class
public class Customer {
public Guid Id { get; set; }
public string Description { get; set; }
}
Customer c = new Customer() { Id = Guid.NewGuid(), Description = "Toaster" };
var repo = new SimpleRepository("CustomerTest",
SimpleRepositoryOptions.RunMigrations);
repo.Add(c);
If I run this code it works perfectly, creates a table "Customer" and inserts the row for the toaster. However if I decide to change my Customer class to:
public class Customer {
public Guid Id { get; set; }
public string Description { get; set; }
public int Cost { get; set;}
}
And run the same code adding a value for the Cost property the database table remains "Id, Description". If I create a totally new class and past in the Customer fields it will create the table correctly the first time and again any changes dont appear to work.
Any help?
First off all, you should try to figure out if subsonic detects your class definition changes properly.
This code should give you a overview of the statements subsonic want's to execute.
var migrator=new SubSonic.Schema.Migrator(Assembly.GetExecutingAssembly());
var provider=ProviderFactory.GetProvider("CustomerTest");
string[] commands=migrator.MigrateFromModel<Customer>(provider);
commands should contain all changes subsonic wants to make to your database.
You can execute these commands by yourself with:
BatchQuery query = new BatchQuery(provider);
foreach(var s in commands)
query.QueueForTransaction(new QueryCommand(s.Trim(), provider));
//pop the transaction
query.ExecuteTransaction();
(code taken from http://subsonicproject.com/docs/3.0_Migrations).
That said, I suppose commands will be empty in your case.
In that case that could be caused by a statement that is not implemented by the provider you are using (SqlServer/MySQL/SQLite/Oracle). Maybe you should download the SubSonic source and step into the migrator.MigrateFromModel(...) method to see what happens.
Another possible cause (if you use MySQL) could be that your information schema is not up to date. I encountered this problem a while ago. After changing my database and regenerating the DAL with SubSonic 2, my generated code didn't change.
I figured out that the mysql information schema (and subsonic does queries on the information schema) hadn't changed yet.
I solved this by executing FLUSH TABLES which caused the information scheme to reload. I don't know if that's a bug in mysql or desired behaviour but you should try FLUSH TABLES first.

Categories