SCOPE_IDENTITY Exception - dapper-simplecrud

I have been evaluating the use of dapper and the simplecrud extension with sqlite. No matter what I try when doing a table insert things fail with an exception
no such function SCOPE_IDENTITY
Table class
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
Simplest piece of code to test
static void Main( string[] args )
{
SQLiteConnection conn = new SQLiteConnection( "Data Source=E:\\Databases\\MyDatabase.db;Version=3" );
conn.Open();
var usr = new User { Name = "Dave", Age = 65 };
var id = conn.Insert(usr);
conn.Close();
}
As indicated earlier when I run the code the data is inserted into the table but the program terminates with the SCOPE_IDENTITY exception.
Any assistance would be greatly appreciated

Judging from the Github page, it seems the current release has dropped support for SQLite:
Database support
There is an option to change database dialect. Default is Microsoft SQL Server but can be changed to PostgreSQL or MySQL. We dropped SQLite support with the .Net Core release.
SimpleCRUD.SetDialect(SimpleCRUD.Dialect.PostgreSQL);
SimpleCRUD.SetDialect(SimpleCRUD.Dialect.MySQL);
Depending on which version you have, you might be able to use a similar call to set the SQLite "dialect" (if it's still supported in your code base).

i was using dapper fastCrud i face the same issue. so add this line of code in my constructor.
OrmConfiguration.DefaultDialect = SqlDialect.SqLite;

Related

SocketException while trying SaveChanges on a list of blobs with Entity Framework and MariaDB using Pomelo NUGET package

I would like to switch from SQLExpress to MariaDB, but run into an issue with SaveChanges.
I can replicate the exception related to the byte[] with a console test application easily using this code, which runs perfectly if I try the same on SQLExpress.
What puzzles me is:
TestScenario 1: Put the byte[] into TestTable class, it works with MariaDB.
TestScenario 2: Replace the list of SubTable with just one instance of subtable. -> Works
TestScenario 3: Replace the byte[] in SubTable by e.g. a single int -> again works
Each time I used add-migration and update-database prior to running the code.
The error message I am getting is:
"SocketException: Eine bestehende Verbindung wurde softwaregesteuert
durch den Hostcomputer abgebrochen."
"SocketException: Failed to read the result set."
I am using the latest version from Pomelo as well as EFCore via NUGET manager.
Honestly I am at a loss. The only information I could find on google was to check the maximum package size setting, but this is well above the blob size for my DB.
So here is my code:
A simple TestTable class with a List of SubTables.
public class TestTable
{
public int ID { get; set; }
public List<SubTable> sub { get; set; } = new List<SubTable>();
}
public class SubTable
{
public int ID { get; set; }
public int ParentID { get; set; }
public SubTable Parent { get; set; } //<- see Update Mai, 19th, 2020 below
public byte[] blob { get; set; } //<- here is the root cause for the issue (see Update Mai, 19th, 2020)
}
SubTable contains the blob as an array of bytes.
The ModelContext is derived from DBContext so nothing fancy here. Just the connection string, which needs to be adapted to the specific system.
public partial class ModelContext : DbContext
{
public DbSet<TestTable> TestData { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySql(#"Server=<IP>;Database=<DB>;User Id=<ID>;Password=<PW>;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
}
In the main part of the console app, I create the ModelContext and initialize my datastructure. I am using Code-First approach, having the database created by using add-migration and update-database.
class Program
{
static void Main(string[] args)
{
using (var db = new ModelContext())
{
TestTable t = new TestTable();
for (int index = 0; index < 4000; index++)
t.sub.Add(new SubTable() { blob = new byte[5000] });
db.TestData.Add(t);
db.SaveChanges(); // <- at this point the exception is raised
}
Console.WriteLine("Done!");
}
}
}
This is how the migration part of subtable looks like:
migrationBuilder.CreateTable(
name: "SubTable",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ParentID = table.Column<int>(nullable: false),
blob = table.Column<byte[]>(nullable: true),
TestTableID = table.Column<int>(nullable: true)
},
So basically this is a standard scenario which can be found on numerous web sites and blogs, if there would not be the exception, which I do not understand.
Any help/suggestions apprechiated.
UPDATE 2020 Mai 19:
Out of curiosity, I again tried to solve the issue. So I installed the newest version of MariaDB.
I received an error message indicating something is wrong with the
foreign key design.
Double checking the foreign key, I found a bug
in my code. public SubTable Parent { get; set; } should be:
public TestTable Parent { get; set; }
--> Now it works just fine with the newest version of MariaDB.
The MariaDB version (V5.5.xx) running on my NAS won't though. Sad but definetly not a show stopper.
So for me the issue is closed, as it seems to be related to an outdated version of MariaDB.
Cheers,
Axel

Can't create related entity in ASP.NET Core with EF Core

I have a problem creating a related entity in Entity Framework Core 2.0. I've just created the solution, consisting of an Asp.Net Core backend project, and a UWP project to act as client. Both solutions share model. The two models are:
public class UnitOfWork {
public int UnitOfWorkId { get; set; }
public string Name { get; set; }
public Human Human { get; set; }
}
public class Human {
public int HumanId { get; set; }
public string Name { get; set; }
public List<UnitOfWork> WorkDone { get; set; }
}
As you can see, model is very simple. One human has many units of work. By the way, the backend is connected to an Azure SQL database. I've seen the migration classes, and the database schema looks good to me.
The problem I have is when I want to create a unit of work referencing an existing human, using HTTP. The controller is fairly simple:
[HttpPost]
public UnitOfWork Post([FromBody] UnitOfWork unitOfWork) {
using (var db = new DatabaseContext()) {
db.UnitsOfWork.Add(unitOfWork);
var count = db.SaveChanges();
Console.WriteLine("{0} records saved to database", count);
}
return unitOfWork;
}
Again, nothing fancy here.
How can I create an unit of work, and assign it to an existing human? If I try it with an existing human, in this way
var humans = await Api.GetHumans();
var firstHuman = humans.First();
var unitOfWorkToCreate = new UnitOfWork() {
Name = TbInput.Text,
Human = firstHuman,
};
I get this error:
Cannot insert explicit value for identity column in table 'Humans' when IDENTITY_INSERT is set to OFF
I feel that setting IDENTITY_INSERT to ON will solve my problem, but this is not what I want to do. In the client, I'll select an existing human, write down a name for the unit of work, and create the latter. Is this the correct way to proceed?
EDIT: Following #Ivan Stoev answer, I've updated the UnitOfWork controller to attach unitofwork.Human. This led to
Newtonsoft.Json.JsonSerializationException: 'Unexpected end when deserializing array. Path 'human.workDone', line 1, position 86.'
Investigating - seen here - EFCore expects to create collections (like human.WorkDone) in the constructor, so I did it, and no more nulls deserializing. However, now I have a self-referencing loop:
Newtonsoft.Json.JsonSerializationException: Self referencing loop detected with type 'PlainWorkTracker.Models.UnitOfWork'. Path 'human.workDone'.
Any ideas? Thanks!
The operation in question is falling into Saving Disconnected Entities category.
Add methods marks all entities in the graph which are not currently tracked as new (Added) and then SaveChanges will try to insert them in the database.
You need a way to tell EF that unitOfWork.Human is an existing entity. The simplest way to achieve that is to Attach it (which will mark it as Unchanged, i.e. existing) to the context before calling Add:
db.Attach(unitOfWork.Human);
db.Add(unitOfWork);
// ...

Sql Ce & EF Usage (self coded)

I have a Windows Program which should be deployed without writing to AppData during Installation, but i want a Sql CE Database in there.
So i have 2 Ideas: Deploying it to Programs and then Copying on first start up, or, what i would prefer, Coding everything.
So i found this Thread Deploying VS2010 Database Projects Without VSDBCMD? which basically tells me its a bad idea, but i don`t think the Answerer is allknowing and i have a better Idea. I found that Piece of Code somewhere:
string connStr = "Data Source = FooDatabase.sdf; Password = SomePassword";
if (File.Exists("FooDatabase.sdf"))
File.Delete("FooDatabase.sdf");
SqlCeEngine engine = new SqlCeEngine(connStr);
engine.CreateDatabase();
using (var conn = new SqlCeConnection(connStr)) {
conn.Open();
SqlCeCommand cmd = conn.CreateCommand();
cmd.CommandText = "CREATE TABLE FooTable(col1 int, col2 ntext)";
cmd.ExecuteNonQuery();
from here: Create SQLCE database programmatically
what i am asking is, if this works on any PC and what i have to do code to use Entity Framework. I was thinking of something like
public class FooContext : System.Data.Entity.DbContext
{
public FooContext() : base("Data Source = FooDatabase.sdf; Password = SomePassword") { }
public DbSet<FooTable> FooTables { get; set; }
}
public class FooTable
{
public int col1 { get; set; }
public string col2 { get; set; }
}
but i just dont get it to work.
might be that only the connectionstring is wrong, but how do i avoid using it or how does the right one look like?
Help plz?
Try to use this in your startup logic
private static void InitializeDB()
{
const string connectionString = "Data Source = FooDatabase.sdf; Password = 123";
Database.DefaultConnectionFactory = new
SqlCeConnectionFactory("System.Data.SqlServerCe.4.0", "", connectionString);
}
take a look at this post

EF Upgrade from 4.0.0 to 4.3.1 causing strange errors

I have just upgraded from EF 4.0.0 to EF 4.3.1.
I am using Visual Studio 2010 Ultimate on Windows XP updated to latest release and all Windows updates/patches applied. The database engine I'm using is SQL Server 2008 R2 Developers Edition.
The following code works perfectly under EF 4.0.0 but not under EF 4.3.1.
public class ItemBase
{
public DateTime Created { get; set; }
public int CreatedByUserID { get; set; }
public DateTime LastModified { get; set; }
public int LastModifiedByUserID { get; set; }
public User CreatedBy { get; set; }
public User LastModifiedBy { get; set; }
public ItemBase()
{
CreatedByUserID = -1;
LastModifiedByUserID = -1;
CreatedBy = null;
LastModifiedBy = null;
}
}
public class User : ItemBase
{
public int UserID { get; set; }
public string LoginName { get; set; }
public string Password { get; set; }
public string EmailAddress { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string DisplayName { get; set; }
public User() : base()
{
UserID = -1;
LoginName = String.Empty;
Password = String.Empty;
EmailAddress = String.Empty;
Firstname = String.Empty;
Lastname = String.Empty;
DisplayName = String.Empty;
}
}
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().Property(u => u.UserID).HasDatabaseGenerationOption(DatabaseGenerationOption.Identity);
}
The only thing that has changed is the version of Entity Framework I'm using.
I have checked the references etc and everything is as expected.
As you can see from the code above, the User class inherits from ItemBase which in turn has a reference to a User instance. The underlying User table contains all the properties from the User class and the ItemBase class (except for the two navigation properties public User CreatedBy { get; set; } and public User LastModifiedBy { get; set; })
Running this code under 4.0.0 everything works as expected, not a single problem or issue whatsoever.
BUT, when I run the same code under 4.3.1 (without any changes whatsoever to anything else, including the database I'm using) I get the following error:
"Unable to determine the principal end of an association between the types 'User' and 'User'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations."
So I then added the following two lines to the OnModelCreating method:
modelBuilder.Entity<User>().HasRequired(u => u.CreatedBy).WithMany().HasForeignKey(k => k.CreatedByUserID);
modelBuilder.Entity<User>().HasRequired(u => u.LastModifiedBy).WithMany().HasForeignKey(k => k.LastModifiedByUserID);
I then get these strange errors:
"The provider did not return a ProviderManifestToken string."
"A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections.
(provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)"
I also noticed loads and loads of these errors in the output window:
"A first chance exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll"
However, these errors appear to be a bit of a red-herring, as the database is fine, available, and the connection string is perfect too. If I subsequently undo the changes to the OnModelCreating method I get the original error again, so I don't believe the error messages I'm getting actually reflect the underlying problem that's occurring here.
So, based on all of this, I come to the following conclusions:
There is a bug in version 4.3.1 of the Entity Framework?
The fact that my code worked under 4.0.0 without the extra two lines
in the OnModelCreating method was probably due to checks not being
made in 4.0.0 which are now subsequently being made in 4.3.1?
I need to add something extra to my configuration/code, or I'm
missing something else to make this work again under 4.3.1?
Can anyone shed some light on this for me? Its driving me nuts!
Many thanks for your time on this.
Kind Regards
Steve
It looks like you have been using a pre-release version of EF 4.1. Probably CTP4 or CTP5. This is apparent because:
ModelBuilder was renamed to DbModelBuilder before 4.1 RTM
DatabaseGenerationOption was renamed to DatabaseGeneratedOption
The exception you are seeing was introduced before EF 4.1 was RTM'ed
Given this, I'm not 100% sure what model was being created with the pre-release version you were using. With 4.1 and above the two navigation properties are detected as inverses of each other and Code First tries to make a 1:1 relationship between User and User. Code First cannot determine the principal for this relationship so rather than guessing it throws asking you to provide it.
However, looking at your model it is clear that this is not what you want anyway. It seems much more likely that you want two 1:* uni-directional navigation props--one for CreatedBy and one for LastModifiedBy. This is what you setup in your OnModelCreating call.
With the changes made to the names of the classes to match 4.1/4.3 and with the code added to OnModelCreating, your code works fine for me on EF 4.3.1.
With regard to not being able to make the connection, you say that the connection string is correct, in which case it must be a case of EF not finding it. Assuming it is in your app.config, then you need to pass the name of it to the DbContext constructor. For example:
public class MyContext : DbContext
{
public MyContext()
: base("name=MyConnectionStringName")
{
}
}
If you're using the connection string in some other way then we'll need more details on that.

EF 4.1, POCO: Reference type properties are not updated in case AutoDetectChanges=false

EF 4.1, POCO: I turned off AutoDetectChanges (Configuration.AutoDetectChangesEnabled = false) to speed up data update. Then I run Add or Attach with entity state changed to EntityState.Modified. All this causes references to other objects not being updated in database. However all scalar properties are updated successfully.
Profiler shown EF generates SQL update operation for every scalar property, but not for reference type, though I really changed its value in my code. This issue reproduced for every type of entity in my model.
Add operation or Attach with EntityState.Added both work fine. If I turn AutoDetectChanges back on, everything works fine as expected for updated records too.
Help me please to figure out what's wrong. I can not find any good comprehensive documentation on EF's Detect Changes.
UPDATE
I was asked to put some example of code to reproduce the issue. Domain:
public class Client
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Address Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public virtual string City { get; set; }
}
DataContext:
public class DataContext : DbContext
{
public DbSet<Client> Clients { get; set; }
public DbSet<Address> Address { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Client>().HasOptional(c => c.Address);
}
}
Add one record to Clint table and one to Address. Point Client to the Address. Then run the following code:
using (var cntx = new DataContext())
{
cntx.Configuration.AutoDetectChangesEnabled = false; // Reason of problem
var client = cntx.Clients.First();
client.Name = "Anna"; // This property will be updated
client.Address = null; // This property will not be updated
cntx.Clients.Attach(client);
cntx.Entry(client).State = EntityState.Modified;
cntx.SaveChanges();
}
This code does generates SQL script like this:
update [dbo].[Clients] set [Name] = 'Anna'
where ([Id] = 1)
Set AutoDetectChangesEnabled to true and run the code again, this time everything alright:
update [dbo].[Clients]
set [Name] = 'Anna', [Address_Id] = null
where (([Id] = 1) and [Address_Id]=1)
Note it does not matter if you change Address's value from specific value to null, or back to specific value, or one concrete value to other concrete value, any change is not tracked while AutoDetectChanges=false. Seems like EF bug.
See Change Tracking on MSDN
Well, I found out the way to set Reference property values that works even with AutoDetectChangesEnabled=false:
cntx.Entry(client).Reference(c => c.Address).CurrentValue = null;
However I definitely do not like it. 1) Code looks ugly; 2) You have to have access to context to make it work, which is not my case, I'd like this property being set outside of repository which only has access to DbContext. Is any other simpler way to let EF know the property value is changed?
Updated: Ok, I found simpler workaround: just run cntx.ChangeTracker.DetectChanges() before running cntx.SaveChanges(). It helps EF generate correct SQL update script