EF5 Database Migration with MySql - mysql

I encountered the below error when executing Enable-Migrations command against a MySql database:
PM> Enable-Migrations -ContextTypeName CodeFirstEFMySqlA1.Models.DataContext
Checking if the context targets an existing database...
System.ArgumentOutOfRangeException: startIndex cannot be larger than length of string.
Parameter name: startIndex
at System.String.InternalSubStringWithChecks(Int32 startIndex, Int32 length, Boolean fAlwaysCopy)
at System.Data.Entity.Migrations.DbMigrator.ScaffoldInitialCreate(String namespace)
at System.Data.Entity.Migrations.Design.MigrationScaffolder.ScaffoldInitialCreate()
at System.Data.Entity.Migrations.Design.ToolingFacade.InitialCreateScaffoldRunner.Scaffold(MigrationScaffolder scaffolder)
at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.RunCore()
at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.Run()
startIndex cannot be larger than length of string.
Parameter name: startIndex
The project was created using:
- ASP.NET MVC4
- EF5 Code First
- MySql Database Server
- MySql.Data, MySql.Data.Entity
- A custom database initializer was implemented using System.Data.Entity.IDatabaseInitializer for creating migration history table.
Model:
public class Product
{
[Key]
public int Id { get; set; }
[Required, MaxLength(100)]
public string Name { get; set; }
public int Rank { get; set; }
[MaxLength(100)]
public string Type { get; set; }
}
After executing the command "Enable-Migrations" the Configuration.cs class was generated but no migration classes were generated. The same error "startIndex cannot be larger than length of string" is raised if I try to execute "Add-Migration" command.
My attempt is to test how well EF5 Code First and Database Migration capabilities could be used against a MySql database server. As I see database creation can be done using a custom database initializer, however I could not get database migrations working.
Any thoughts on this problem are highly appreciated
Thanks in advance!!

Thanks to Kirk Woll, I was able to find a solution for the above problem.
I used MySQL Data Connector v.6.6.4 and it has built in support for EF 5. Now Database Migrations works without a problem with MySql. Just to note I had to delete the previous database and let EF create a new one with Update-Database command.
Reference: MySQL 5.5 + .NET Connector + Entity Framework + Migrations = FormatException

Related

A network-related or instance-specific error occurred while establishing a connection to SQL Server. Code-first ef core 6

I am building my first application using .Net 6 EF Core.
I want to use the code-first method.
When I try to migrate using Update-Database (after I get this error:
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: Named
Pipes Provider, error: 40 - Could not open a connection to SQL Server)
I have a "local instance of MySQL80" running on my machine. I can connect to it, using a DB tool, like Dbeaver or the MySQL Workbench.
This is the Connection String I am using:
"ConnectionStrings": {
"DevConnection": "Server=localhost;Database=my-desired-db-name;Trusted_Connection=True;"
}
This is my Program.cs:
using Microsoft.EntityFrameworkCore;
using react_chores_prototype_api.Models;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddDbContext<MyDBContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DevConnection")));
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseAuthorization();
app.MapControllers();
app.Run();
I know that this question came up a few times already, but I cant find a solution with the given explantations, also because of lots of different versions over the years. If someone can maybe help me, so i can start working on my project, that would be greatly appreciated.
EDIT:
I installed Pomelo MySql Provider and changed the connectionString to a mysql one.
Also i changed my Program.cs like this:
var conString = "Server=localhost;Database=my-db-name;Uid=root;Pwd=verySecurePw;";
builder.Services.AddDbContext<MyDBContext>(options => options.UseMySql(connectionString: conString, ServerVersion.AutoDetect(conString)));
Now it seems to work, I just get following SQL Syntax Error (Not really related to the original Question I guess):
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'NOT NULL,
Description nvarchar(200 NOT NULL,
Points int NOT NULL,
Related to this Model:
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace react_chores_prototype_api.Models
{
public class Task
{
[Key]
public int Id { get; set; }
[Column(TypeName = "nvarchar(50)"]
public string Name { get; set; }
[Column(TypeName = "nvarchar(200)"]
public string Description { get; set; }
public int Points { get; set; }
}
}

.Net Core2 EF MySQL having issue while changing foreign key column to nullable

I am working on an application where I am using .Net Core 2, EF Core and MySQL as database server via Code First approach.
I have 2 tables:
User
Employee
User table is the main table which contains the user information and Employee table is the child table which has a column ID_User as shown below:
public class User : BaseEntity
{
public int ID_User { get; set; }
public string Name { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public virtual ICollection<Employee> Employees{get;set;}
}
public class Employee : Entity
{
public int ID_Employee { get; set; }
public string Name { get; set; }
public int ID_User { get; set; }
public virtual User User { get; set; }
}
Everything works perfectly when I use the above mapping and I have enough data in both the tables.
Now, I want to make the column ID_User in Employee table as nullable
To implement this change I made following change to my model:
public class Employee : Entity
{
public int ID_Employee { get; set; }
public string Name { get; set; }
public int? ID_User { get; set; }
public virtual User User { get; set; }
}
and in mapping file:
builder.HasOne(x=>x.User).WithMany(y=>y.Employees).HasForeignKey(z=>z.ID_User).IsRequired(false);
After running the dotnet ef migrations add empuser command it generated the following migration code:
migrationBuilder.DropForeignKey(
name: "FK_Employee_User_ID_User",
table: "Employee");
migrationBuilder.AlterColumn<int>(
name: "ID_User",
table: "Employee",
nullable: true,
oldClrType: typeof(int));
migrationBuilder.AddForeignKey(
name: "FK_Employee_User_ID_User",
table: "Employee",
column: "ID_User",
principalTable: "User",
principalColumn: "ID_User",
onDelete: ReferentialAction.Restrict);
Now when I run dotnet ef database update it is giving me the following error:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'CONSTRAINT FK_Employee_User_ID_User' at line 1
Please help.
Thanks
Try putting the SQL statements directly into the MySQL Workbench.
Type "dotnet ef migrations script" in your commandprompt.
Copy the generated SQL script.
Paste it into your Workbench.
Check where the errors occur.
When I got similar errors using EF core 2 with MySQL this helped me understand the problem better and helped solve the problem. (for me it was a typing error). You can at least use this method to determine if it is an error in the migrations or in your SQL statements.
I know this is not a concrete solution, but I hope this will help you understand your problem and solve it :)
Have you checked foreign key name in database?
I have found bug from migration builder, where creating new table:
In my case I use EF Core 2.1 Mysql DotNet Connector bug
Where migration builder creates wrongly named foreign key name...
To avoid this wrongly named foreign key name:
fix for migration builder
If your foreign key is named wrongly, you can manually rename it in database and then your migration might work.
The key word CONSTRAINT is not supported for certain version of MYSQL . EF core generates drop constraint for dropping foreign key . I have to change the following:-
migrationBuilder.DropForeignKey(
name: "FK_XXXXX",
table: "XXXXXX");
to
migrationBuilder.Sql("ALTER TABLE XXXXXX DROP FOREIGN KEY FK_XXXXX");

Problems migrating ASP.NET Core Identity from SQL Server to MySQL

I am working on migrating my ASP.NET Core project from using Microsoft SQL Server to MySQL now that the MySQL DB provider has been released("pre-released"). I was using Core Identity for membership when using SQL Server and it worked in that configuration. When I migrated the DB to MySQL (using the migration wizard in MySQL Workbench), I began receiving this error when saving a new user to the DB:
No mapping to a relational type can be found for the CLR type 'Microsoft.EntityFrameworkCore.Metadata.Internal.Property'
The error comes in this code when executing the CreateAsync method:
public IActionResult Register([FromBody]RegisterViewModel obj)
{
if (ModelState.IsValid)
{
IdentityUser user = new IdentityUser();
user.UserName = obj.Username;
user.Email = obj.Email;
IdentityResult result = _userManager.CreateAsync(user, obj.Password).Result;
}
}
Here is my DbContext class:
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace PilotMaltApiCore.Models
{
public class PilotDbContext : IdentityDbContext<IdentityUser, IdentityRole, string>
{
public PilotDbContext(DbContextOptions<PilotDbContext> options)
: base(options)
{
//nothing here
}
public DbSet<Batch> Batches { get; set; }
public DbSet<Bag> Bags { get; set; }
public DbSet<Vendor> Vendors { get; set; }
public DbSet<Variety> Varieties { get; set; }
}
}
I was thinking it may have something to do with the difference in datatypes between SQL Server and MySQL. Here is the SQL Server table:
And here is the MySQL table after using the migration wizard in MySQL Workbench:
Keep in mind, all of the code worked fine when using SQL Server. Your help is appreciated, thanks!
This tutorial worked well for me:
http://blog.developers.ba/asp-net-identity-2-1-for-mysql/
I changed the charset for the varchar fields to utf8mb4 which fixed the issue.
I also chose to use Sapient Guardian's version of the MySql provider for .net Core and which has proved much less problematic than MySql's version. It can be downloaded here.

Fluent Nhibernate and Sql Server private setter error

I'm trying to complete some first step with fluent nhibernate with sql server express, to add this features in my project.
But got some errors. As I'm newbie to nhibernate, couldn't solve a problem for some time.
I have an entity with
Id { get; private set; }
accessors. And this entity is mapped to table with identity {1,1} column in sql server.
But during creating Session factory, I get an error:
The following types may not be used as proxies:Entity: method set_Id should be 'public/protected virtual' or 'protected internal virtual'
I understand that private setter is used to encapsulate setting of this property, but why do I get this error then?
PS: example on site of fluent for nhibernate is using sqllite db and everything is just fine.
This is an issue that has caused grief for many NH/FNH users, including me.
Until recently, NHibernate has allowed private setters with proxy objects. But starting with NH 3.2, private setters are no longer allowed - they must be "'public/protected virtual' or 'protected internal virtual'", as the error message says.
This is a breaking change for a lot of the FNH/NH sample code that's out there, and is especially confusing to newbies.
Declare the property as public virtual int Id { get; protected set; }. The proxy object generated by NHibernate will then be able to set the property.
Another solution can be to use a backing field:
private int id;
public int Id
{
get { return id; }
}
And then use mapping:
Map(x => x.Id).Access.CamelCaseField();

PLINQO / LINQ-To-SQL - Generated Entity Self Save Method?

Hi I'm trying to create a basic data model / layer
The idea is to have:
Task task = TaskRepository.GetTask(2);
task.Description = "The task has changed";
task.Save();
Is this possible? I've tried the code below
Note: The TaskRepository.GetTask() methods detaches the Task entity.
I'd expect this to work, any ideas why it doesnt?
Thanks
public partial class Task
{
// Place custom code here.
public void Save()
{
using (TinyTaskDataContext db = new TinyTaskDataContext { Log = Console.Out })
{
db.Task.Attach(this);
db.SubmitChanges();
}
}
#region Metadata
// For more information about how to use the metadata class visit:
// http://www.plinqo.com/metadata.ashx
[CodeSmith.Data.Audit.Audit]
internal class Metadata
{
// WARNING: Only attributes inside of this class will be preserved.
public int TaskId { get; set; }
[Required]
public string Name { get; set; }
[Now(EntityState.New)]
[CodeSmith.Data.Audit.NotAudited]
public System.DateTime DateCreated { get; set; }
}
#endregion
}
Having done some reading I've realised I was implmenting the Repository pattern incorrectly. I should have been adding the Save method to the repository for conventions sake.
However, the actually problem I was having with regard to commiting the disconnected dataset was due to optimistic concurrency. The datacontext's job is to keep track of the state of it's entities. When entities become disconnected you loose that state.
I've found you need to add a timestamp field to the database table or I can set the UpdateCheck field on each column in my dbml file.
Here is some info about the UpdateCheck
Some useful links about disconnected Linq and plinqo
Great info on implementing the Repository pattern with LINQ
Short tutorial for implementing for updating and reattaching entities
Previously answer question
Rick Strahl on LINQ to SQL and attaching Entities
There is no need for this line (Task task = new Task();). The above should work although I've never seen it implemented in this manner. Have you thought about using the managers? Are you running into any runtime errors?
Thanks
-Blake Niemyjski