I have a problem with strange generated SQL in ef4 ctp5.
I have simple model with mapping :
[Table("post_auction")]
public class PostAuction
{
[Key,Column(Name="Id"),DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGenerationOption.Identity)]
public int Id { get; set; }
[Column(Name = "Number")]
public int Number { get; set; }
[Column(Name = "Label")]
public string Label { get; set; }
[Column(Name = "Description")]
public string Description { get; set; }
[Column(Name = "CategoryId")]
public int PostAuctionCategoryId { get; set; }
[Column(Name = "PriceCZK")]
public int PriceCZK { get; set; }
[NotMapped]
public bool IsAuctionPhotoExitst
{
get
{
if (File.Exists(HttpContext.Current.Server.MapPath("~/Public/Images/Posts/Thumbs/small_" + this.Number + ".jpg")))
return true;
return false;
}
}
}
and my linq query is :
_rovastampDbContext.PostAuctions.Where(x => x.PostAuctionCategoryId == auctionId).OrderBy(x => x.Id).ToList();
Ef4 profiler shows me
SELECT
[Project1].[Id] AS [Id],
[Project1].[Number] AS [Number],
[Project1].[Label] AS [Label],
[Project1].[Description] AS [Description],
[Project1].[CategoryId] AS [CategoryId],
[Project1].[PriceCZK] AS [PriceCZK]
FROM
(SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Number] AS [Number],
[Extent1].[Label] AS [Label],
[Extent1].[Description] AS [Description],
[Extent1].[CategoryId] AS [CategoryId],
[Extent1].[PriceCZK] AS [PriceCZK]
FROM
[dbo].[post_auction] AS [Extent1]
WHERE
[Extent1].[CategoryId] = 1 /* #p__linq__0 */) AS [Project1]
ORDER BY
[Project1].[Id] ASC
My question is a pretty simple : Why ef4 generate that complicated query, when right one is
SELECT ...
FROM TABLE
WHERE CategoryId = 1
ORDER BY Id ASC
Thanks for your advice :)
Martin
EDIT : If I let EF to create db automatic, the problem with query persists...
Excellent question. I'm guessing that it's a bug, since my (edmx-generated) Entity Framework context doesn't produce a projection the way yours does. I would report it as a bug.
Yeah for sure, looks like Beta-garbled code gen to me. I just tried it too with LINQ-SQL, nothing similar. Be sure to report it!
Related
I am trying to create table in memory db using Linq2Db, and SQLiteDataProvider in a netcore3.1 application.
And if mapping class has a property with attribute
[Column(DataType=DataType.DateTime2, Precision=3), Nullable ]
it gives me the following syntax error :
Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'near ")": syntax error'.
I dig for the query it generates and its this:
CREATE TABLE [testTable]
(
[Id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
[Created] DateTime2(3, ) NULL
)
Here is an example that I'm trying:
using System;
using LinqToDB;
using LinqToDB.Data;
using LinqToDB.Mapping;
namespace InMemoryDb
{
class Program
{
static void Main(string[] args)
{
DataConnection.AddConfiguration("default", "Data Source=Sharable;Mode=Memory;Cache=Shared",
new LinqToDB.DataProvider.SQLite.SQLiteDataProvider("SQLite.MS"));
DataConnection.DefaultConfiguration = "default";
using var db = new DataConnection("default");
db.CreateTable<TestTable>();
}
[Table(Schema="dbo", Name="testTable")]
public class TestTable
{
[Column(DataType=DataType.Int32), PrimaryKey, Identity]
public int Id { get; set; }
[Column(DataType=DataType.DateTime2, Precision=3), Nullable]
public DateTime? Created { get; set; }
}
}
}
why its generates query with DateTime2(3, ) and not a correct one DateTime2(3)?
Try this as workaround
[Column(DbType="DateTime2(3)", Nullable ]
You can use possibility of linq2db to define schema for several databases.
Note that there is no DateTime type in SQLite.
[Table(Schema="dbo", Name="testTable")]
public class TestTable
{
[Column(DataType=DataType.Int32), PrimaryKey, Identity]
public int Id { get; set; }
[Column(Configuration=ProviderName.SQLite, DataType=DataType.DateTime2), Nullable]
[Column(DataType=DataType.DateTime2, Precision=3), Nullable]
public DateTime? Created { get; set; }
}
I am totally not getting this, because I have used this library in Xamarin apps for several years.
I have this base class that contains properties common in all db items:
public class BaseItem
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; } = 0; // SQLite ID
public long CreatedTimeSeconds { get; set; } = DateTime.Now.ToUnixTimeSeconds();
public long ModifiedTimeSeconds { get; set; } = DateTime.Now.ToUnixTimeSeconds();
}
Now, I derive from it:
[Table("CategoryTable")]
public class Category : BaseItem
{
public int CategoryTypeID { get; set; } = (int)CategoryType.Invalid;
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
}
Here's a simplified version of what I'm seeing:
public class DBWorld
{
ISQLiteService SQLite { get { return DependencyService.Get<ISQLiteService>(); } }
private readonly SQLiteConnection _conn;
public DBWorld()
{
_conn = SQLite.GetConnection("myapp.sqlite");
}
public void TestThis()
{
_conn.CreateTable<Category>();
var category = new Category();
category.Name = "This Should Work";
int recCount = connection.Insert(category);
// at this point recCount shows as 1, and category.ID shows as zero.
// I thought Insert was supposed to set the autoincrement primary key
// regardless, it should be set in the database, right? So...
var categoryList = connection.Query<Category>($"SELECT * FROM {DBConstants.CategoryTableName}");
// at this point categoryList[0] contains all the expected values, except ID = 0
}
}
I am obviously missing something, but for the life of me, I can't figure out what...
Like so many other bizarre things that happen in the Visual Studio Xamarin world, when I went back later, this worked the way all of us expect. I guess Visual Studio was just tired and needed to be restarted.
I want to do an update for a specific field on a table based on the results from a query that includes a join. Using OrmLite with ServiceStack.
My Classes are as follows:
public class Document
{
public int Id { get; set; }
public string BCL_Code { get; set; }
public bool IsActive { get; set; }
public int DocumentTypeId { get; set; }
}
public class DocumentType
{
public int Id { get; set; }
public string TypeName { get; set; }
}
Trying to do the Update on the Join with the following code:
var q = db.From<Document>()
.Join<Document, DocumentType>(
(doc, type) => doc.DocumentTypeId == type.Id)
.Where(d => d.BCL_Code == "FR49")
.And<DocumentType>(t => t.TypeName == "Enrollment Process");
db.UpdateOnly(new Document { IsActive = false }, onlyFields: q);
I know I can update specific fields, and I know how to do joins, but when I try to include a join in the query, and then do an UpdateOnly, I get an error message on the db.UpdateOnly line:
The multi-part identifier "DocumentType.TypeName" could not be bound.
Is it possible to do an Update on a Join Query?
If so, what is the proper way to do it?
There's no Typed APIs for Update From Table in OrmLite yet, you can add a feature request for it.
In the meantime you can use Custom SQL, e.g:
db.ExecuteSql(#"UPDATE Document SET IsActive = #isActive
FROM Document d
INNER JOIN DocumentType t ON (d.DocumentTypeId = t.Id)
WHERE d.BCL_Code = 'FR49'
AND t.TypeName = 'Enrollment Process'",
new { isActive = false });
I'm trying to modify the model entity which is sent to the CreateEmployee Method as a parameter to be modified.
public void CreateEmployee(string roleName, EmployeeModel emp)
{
string roleName == "user";
emp.Roles.Select(e => new RoleModel { RoleName = roleName });
AddEmployee(emp);
}
this is how models looks like....
And it give me an error saying
Model does not contain a definition for 'Select' and 'Select' accepting a first argument of type Model could be found....
I have tried using the 'Where' method as well, but still give the same error..
emp.Roles.Where(e => e.RoleName == roleName)
You have some errors in your code,
use = not == for assignment
the selected roles does not used
Linq query functions like Select and Where apply to IEnumerable the Roles property is of type RoleModel not IEnumerable<RoleModel>
so:
public class EmployeeModel
{
//some code
public ICollection<RoleModel> Roles{ get; set; }
}
using System.Linq;
public void CreateEmployee(string roleName, EmployeeModel emp)
{
string roleName = "user";
var empRoles = emp.Roles.Select(e => new RoleModel { RoleName = roleName });
AddEmployee(emp);
}
Edit:
If you want to have one role per employee at most, the relationship between Role and Employee became one-to-many(each role has n employee)
if Role is optional for employee:
public class EmployeeModel
{
//some code
public short? RoleId { get; set; }//nullable foreign key
public virtual RoleModel { get; set; } //Navigation property
}
public class RoleModel
{
//some code
public ICollection<Employee> Employees{ get; set; }
}
But, if Role is required for Employee you must change the foreign key to:
public short RoleId { get; set; }//non-null foreign key
For getting an Employee's Role you do not need to use Select or Where on navigation property, just use employee.Role.
Finally for querying Role's employees you can use Select, Where, ... as mentioned before.
Can any body help me about, how to create simple database and tables programatically and insert values ,step by step procedure in sqlite using monotouch.I am new to this technology .
Thank you..
If you're using sqlite-net (which I highly recommend) you can simply call:
Model
public class Stock
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[MaxLength(8)]
public string Symbol { get; set; }
}
Create
var db = new SQLiteConnection("stocks.db");
db.CreateTable<Stock>();
Insert
var s = db.Insert(new Stock() {
Symbol = symbol });
Query
return db.Query ("select * from Valuation where StockId = ?", stock.Id);