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");
Related
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.
Is it possible to read and write to a SQL Server database using DataTable with Entity Framework?
I have multiple code tables defined in my database such that each of them share a fixed set of properties as shown in the sample below.
For example
public class CTGender
{
public Guid ID { get; set; }
public string Description { get; set; }
public string DisplayValue { get; set; }
//...Other properties specific to CTGender
}
public class CTNationality
{
public Guid ID { get; set; }
public string Description { get; set; }
public string DisplayValue { get; set; }
//...Other properties specific to CTNationality
}
The situation I face right now is the ever expansion of my code tables, could be another CTCountry, CTRole and so on, for example.
I am trying to synchronise these code tables between multiple databases.
The solution is heavily dependent on Entity Framework as the data access.
Is there a generic way for Entity Framework to read and write ALL these code tables without their entity models defined, like how you can read and write generic DataTables using ADO.NET?
Yes, there are couple of ways by which you can create tables at code side then either using code first approach or using publish project mechanism you can generate tables in SQL server using entity framework.
In the latter approach, you can create a separate project where you can write SQL for your various tables. This project should target SQL Server. You can right click on this project and click on publish option for updating all your tables inside SQL server.
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.
I am very new to ASP.Net and MVC applications so pardon me if this question has been asked or is trivial.
I know how to create an entity model class from a database table, but I want to perform a series of Joins and create a Pivot table from an SQL query and then pass this to a view.
However, I do not know a quick way to create an entity class for this.
Currently, I am doing it the long way by manually defining a model class like so:
public class OAData
{
public int Zone { get; set; }
public string Device { get; set; }
public string Part { get; set; }
...
//CONSTRUCTOR
public OAData(int zone, string device, string part...){
Zone = zone;
Device = device;
Part = part;
...
}
}
and then create a database connection in the controller, loop through all the records, creating OAData objects for each record, add it to a list and then pass that list to the View.
Is there an easier way to do this (there are many fields returned by the query)? Can I create a model from a complex SQL query rather than just off a database table?
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).