I want to use SQL Server CE 4, together with EF 6 migrations, for database operations in my integration tests.
The id´s of the entities are Guid´s and some of them are generated by server by using:
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
The others use
.HasKey(x => x.Id);
which are also a Guid but something that is set on the entity before persisting.
However i get following exception when my context calls:
context.saveChanges();
Exception:
{"Server-generated keys are only supported for identity columns. The column 'Id' has type 'SqlServerCe.uniqueidentifier', which is not a valid type for an identity column."}
Is this because sql server ce can´t generate id´s ?
I use same context for SQL Server and it works great.
Yes, due to limitations in the SQL Server Compact engine, it is not possible to get the generated id value back from the engine.
It is possible to set a default
newid()
But the engine offers no way of getting the assigned Guid value after saving (unlike with int values, where you can use ##IDENTITY)
Related
What's the equivalent of NotMapped attribute and AsNoTracking method in Fluent Migrator .Net ORM. I'm migrating one of my project which used EF6 as ORM to Fluent Migrator. I google a lot regarding this but couldn't find any helpful information.
FluentMigrator is an open source project to manage the schema of your data bases, claims to be a .Net implementation similar to Ruby on Rails Migrations, you should post issues and feedback in the issues or discussion forum for that project on github as their community is still active in 2020.
Because Fluent Migrator is not an ORM itself, it only manages the data schema, the question is therefor not properly formed.
EF has it's own schema migration management, Code First Migrations that interprets [NotMapped] to omit the field from the database schema, and to ignore it when mapping results of queries into the data object model.
Project transitions from EF are commonly to NHibernate or Dapper, for this response I will assume NHibernate, because if you were still using EF the problem does not exist but hopefully the thought process will help you find the answer if you are using a different ORM.
RE: NotMapped
As elaborated above, the NotMapped attribute in EF is interpreted by both the data schema migrations AND the ORM. In the configuration for Fluent Migrator you manually specify the fields to manipulate in the data schema, so simply omit the field from Create/Alter table statements altogether.
If you are changing a field to be no longer stored in the database, then you can add a Delete.Column command:
Delete.Column("ColumnName".FromTable("TableName").InSchema("dbo");
UPDATE: Linq2Db solution:
Use NotColumn attribute
In ORMs like NHibernate the same is true, simply do not map the property in the mapping configuration.
This post goes through different solutions when you are using an auto-mapping extension for NHibernate.
RE: AsNoTracking
If you are still using EF6 as the ORM, then this doesn't change, Fluent Migrator is
about schema maintenance and manipulation, not data querying.
AsNoTracking() in an EF query disables change tracking and caching and as a by-product allows a query to return multiple records with duplicate key values in a single response, it is unclear from OP what context AsNoTracking() is being used, but important to identify why is 'might' be used,
UPDATE: linq2Db
As far as I'm aware, Linq2Db does not track changes, its primary function is to translate Linq queries into SQL and execute that SQL, that said AsNoTracking has caching implications so the closest I can find in linq2db is to use NoLinqCache to create a scope where the executions will not be cached:
using (var db = new MyDataConnection())
using (NoLinqCache.Scope())
{
var query = db.Users.Where(x => Sql.Ext.In(x.Id, ids));
}
For readers using NHibernate, you can consult the read-only entities documentation.
You can set al queries in a session as readonly using
session.DefaultReadonly = true
Alternatively you can set a single query to be readonly:
query.SetReadonly(true);
I use EFCore 2.1 Database First approach. I'm pretty familiar with SQL syntax and prefer build queries myself rather then leave this work on EF. I use Table Valued and Scalar Functions for querying the database.
I found this for Scalar
https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-2.0#database-scalar-function-mapping
But unfortunately nothing about Table Functions.
Is there any way to force Visual Studio grab all Table Functions and Scalar Functions and Stored Procedures from SQL Server, when I run Scaffolding?
I was using LINQ to SQL dbml designer before. Everything was extremely simple with dbml. You drag from Server Explorer drop to dbml and boom, I can use SQL Function or SP like regular C# method.
Any chance to reproduce this in EFCore?
There's no reverse engineer (aka DbContext scaffolding) support for it, but you can use FromSql() to query using table-valued functions. See these docs.
var searchTerm = "EF Core";
var blogResults = db.Blogs.FromSql(
"SELECT * FROM dbo.SearchBlogs({0})",
searchTerm);
Source : https://www.allhandsontech.com/data-professional/entityframework/entity-framework-core-advanced-mapping/
Use HasDbFunction to do a mapping, refer Microsoft doc
It requires return types to be declared as Keyless entity using HasNoKeyMicrosoft doc
Configure EF Context to expose Db function
modelBuilder.HasDbFunction(typeof(SalesContext)
.GetMethod(nameof(NameAndTotalSpentByCustomer)))
.HasName("CustomerNameAndTotalSpent");
modelBuilder.Entity<CustWithTotalClass>().HasNoKey();
Invoke Db function in calling code
_context.NameAndTotalSpentByCustomer().Where(c=>c.TotalSpent>100).ToList();
Generated SQL
SELECT [c].[Name], [c].[TotalSpent]
FROM [dbo].[CustomerNameAndTotalSpent]() AS [c]
WHERE [c].[TotalSpent] > 100
How to connect Active Reports 7 to use a stored procedures? I have stored procedures already written, but how do you connect to them to use the data in the tables so that my report is dynamic.
ActiveReports 7 has two different report types, with slightly different ways of using stored procedures.
If you are using a SectionReport (i.e. the traditional form of report that was available in ActiveReports 6) then you can execute a stored procedure via the EXEC SQL command in your query. f.e.
EXEC sp_mysp '<%myparameter%>'
In a PageReport (i.e. the new report type introduced in ActiveReports 7) then you need to set the command type to Stored Procedure and then the query string is set to the name of your stored procedure. If you have any parameters to pass then you can pass them in via the DataSet's parameters page.
In PageReports when working with the ADO.NET based data providers (SQL Server, OLE DB, and Oracle connection types) there is a 1-to-1 correlation between objects in the data source, data set, and parameters in Page Reports and what you see in the related ADO.NET *Connection, *Command, and *Parameter classes. So if you have questions about how those work you can just look at how you would write the same code with the ADO.NET classes.
Using EF4 /w SQL Server 2008.
The following code (against a table with a PK, defined as Int IDENTITY(1,1):
ctx.AddObject(GetEntitySetName(), newEntity);
ctx.SaveChanges();
The results when profiling SQL are the insert statement following by a lookup against the table I'm inserting into:
SELECT ID FROM Table
WHERE ID = ##ScopeIdentity AND ##RowCount > 0
Is there a way to prevent EntityFramework from retreiving the Identity seed? I don't need the ID back in my .Net code and under high volume situations it seems like a wasted operation.
Altenatively, is there a way to tell EF to change the way it performs this operation? The strategy used goes against recommendations made by Microsoft in this defect report:
http://connect.microsoft.com/SQL/feedback/ViewFeedback.aspx?FeedbackID=328811
You cannot change this behavior when using database generated keys (properties marked with StorgeGeneratedPattern.Identity). EF needs a real key value for inserted entity so the only way to avoid the query is to not using database generated keys at all and handling it yourselves in the application.
We are using Entity Framework 4 RC on Visual Studio 2010 with DB2 version 9.7.3.4. I also have the VS Add-ins and can see the DB2 database in Server Explorer. I have created a very simple VS console project and it works fine against SQL Server, so I know it is valid. I have references to "IBM.Data.DB2.9.7.3" and "IBM.Data.DB2.Entity" in my project.
In app.config my connnection string is:
<add name="ProductContext"
providerName="IBM.Data.DB2"
connectionString="Database=DB2TEST;User ID=XXXX;PWD=XXXX;Server=XXXX;Persist Security Info=True;"/>
The first statement in my code is a database initializer:
DbDatabase.SetInitializer<ProductContext>(new DropCreateDatabaseIfModelChanges<ProductContext>());
During run-time when I reach a line that causes a change to the data context I get the error:
Model compatibility cannot be checked
because the database does not contain
model metadata.
Since I requested that the database be dropped, this does not seem to be a logical error. Does anyone know what the cause could be?
I would try to inherit from CreateDatabaseIfNotExists first, which will add the EdmMetadata table to the schema. I believe the error is that EF is saying that it cannot find that table.
So
DbDatabase.SetInitializer<ProductContext>(new CreateDatabaseIfNotExists<ProductContext>());
Run it once, then change to DropCreateDatabaseIfModelChanges once the EdmMetadata table exists.
Try removing the IncludeMetadataConvention like this:modelBuilder.Conventions.Remove<System.Data.Entity.Infrastructure.IncludeMetadataConvention>();
To avoid the "dbo" issue, just map all your entities using either DataAnnotation attributes or Fluent mapping:
[Table("Product", SchemaName = "MySchema")]
public class Category { //DataAnnotoaion approach
modelBuilder.Entity<Category>().ToTable("Categories", "MySchema"); //Fluent approach