I have upgraded the .NET version to the latest 6.0, but I cannot use EF Core to migrate. The change of the version makes me feel very unfamiliar, and the information is relatively small. Any information or help you have is great!
What is the problem that you cannot use EF Core for migration? For the .net6 version, the migration changes are not very big. I wrote a simple demo based on some materials, I hope it will be helpful to you.
csproj file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
Then add the database connection configuration in appsettings.json:
"ConnectionStrings": {
"DefaultConnection": "Your Db"
}
Then in the .net6 version, there is no Startup.cs configuration class, and some configuration is done in Program.cs:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<UserContext>(options => options.UseSqlServer(connectionString));
Model:
public class User
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedDate { get; set; }
}
Create context:
public class UserContext:DbContext
{
public UserContext(DbContextOptions<UserContext> options) : base(options) { }
public DbSet<User> Users { get; set; }
}
Then use the migration command:
add-migration MigrationName
update-database
Test:
public class TestController : Controller
{
private readonly UserContext _context;
public TestController(UserContext context)
{
_context = context;
}
public IActionResult Index()
{
User user = new User();
user.Name ="Test";
user.CreatedDate = DateTime.Now;
_context.Add(user);
_context.SaveChanges();
return View();
}
}
Result:
I use Code first migration as an example. If you follow the steps and have problems, you can send out the error, or you can send out the error you are encountering now, and you can read some changes in .net6:
https://gist.github.com/davidfowl/0e0372c3c1d895c3ce195ba983b1e03d
Related
The following code works fine on Ubuntu 18.04 LTS, after using apt to install libc6-dev (required by another dependency) and libsqlite3-mod-spatialite on a fresh 18.04 instance. When running the same process with test console on 20.04.5 LTS I consistently get a Segmentation fault with a core dump.
I have found the following reference to core dumps mentioning PROJ (cartographic projection library used by spatialite) but no real actionable fixes: https://github.com/bricelam/mod_spatialite-NuGet
My project is a simple test console so I can isolate the behavior from other code:
Project includes the following dependencies:
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.9">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.9" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite" Version="6.0.9" />
</ItemGroup>
Program.cs simply creates context via helper, ensures schema was created and inserts 50 dummy records into a basic table.
using Microsoft.Data.Sqlite;
string filePath = "database.db";
SqliteConnectionStringBuilder scb = new SqliteConnectionStringBuilder()
{
Pooling = false,
DataSource = filePath
};
using (TestDataContext context = LocalContextFactory.CreateContext<TestDataContext>(scb.ConnectionString))
{
context.Database.EnsureCreated();
for (int i = 0; i < 50; i++)
{
Guid id = Guid.NewGuid();
context.ObjectData.Add(new ObjectData() { ObjectUniqueId = id, Name = $"{id}" });
}
context.SaveChanges();
}
Console.WriteLine("Success");
Context has 2 entities defined:
using Microsoft.EntityFrameworkCore;
public class TestDataContext : DbContext
{
public TestDataContext()
{
}
public TestDataContext(DbContextOptions<TestDataContext> options) : base(options)
{
}
public virtual DbSet<ObjectData> ObjectData { get; set; }
public virtual DbSet<GeometryData> GeometryData { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ObjectData>(x => {
x.HasKey(e => e.ObjectUniqueId);
x.Property(p => p.ObjectUniqueId)
.HasConversion(s => s.ToString(), s => new System.Guid(s));
});
modelBuilder.Entity<GeometryData>(x => {
x.HasKey(e => e.ObjectUniqueId);
x.Property(p => p.Geometry).HasSrid(4326);
x.Property(p => p.ObjectUniqueId)
.HasConversion(s => s.ToString(), s => new System.Guid(s));
});
base.OnModelCreating(modelBuilder);
}
}
And those entities look like so:
using System.ComponentModel.DataAnnotations.Schema;
[Table("geometry_data")]
public class GeometryData
{
[Column("object_unique_id")]
public System.Guid ObjectUniqueId { get; set; }
[Column("geometry_type_id")]
public System.Int32 GeometryTypeId { get; set; }
[Column("geometry")]
public NetTopologySuite.Geometries.Geometry Geometry { get; set; }
}
[Table("object_data")]
public class ObjectData
{
[Column("object_unique_id")]
public System.Guid ObjectUniqueId { get; set; }
[Column("object_name")]
public string Name { get; set; }
}
Helper class for creating a local Sqlite dbContext with NetTopology enabled:
public static class LocalContextFactory
{
public static TContext CreateContext<TContext>(string connectionString, bool useNetTopologyProvider = true) where TContext : DbContext
{
DbContextOptionsBuilder<TContext> optionsBuilder = new DbContextOptionsBuilder<TContext>();
optionsBuilder.UseSqlite(connectionString, sqliteDbContextOptionBuilder =>
{
if (useNetTopologyProvider)
{
sqliteDbContextOptionBuilder.UseNetTopologySuite();
}
});
optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
TContext context = Activator.CreateInstance(typeof(TContext), optionsBuilder.Options) as TContext;
return context;
}
}
I am a beginner in Azure and I'd like to make connection between an existing Âzure SQL database and an Azure function (timer triggered) using Entity Framework Core.
I've seen so many videos and I've tried so many things, but I really couldn't get it done. If you have any ideas, could you please help me?
Thanks in advance.
Regarding the issue, please refer to the following steps
package
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.15" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.11" />
Define DBcontext
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlServer("<connection string>");
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
function code
[FunctionName("Function1")]
public static void Run([TimerTrigger("0 */5 * * * *", RunOnStartup = true)] TimerInfo myTimer, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
using (var db = new BloggingContext())
{
log.LogInformation("Inserting a new blog");
db.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/adonet" });
db.SaveChanges();
}
}
ExecuteEF Core Migration
Add-Migration InitialCreate
Update-Database
Test
My .Net Core version is 3.0.100-preview6-012264. You can ask me why I use the preview version. The main reason is useful work with GRPC (scaffolding for this). Now I would like to use entity framework in my project. I have the following .csproj:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Protobuf Include="Protos\dashboard.proto" GrpcServices="Server" Generator="MSBuild:Compile" />
<Protobuf Include="Protos\users.proto" GrpcServices="Client" Generator="MSBuild:Compile" />
<Protobuf Include="Protos\anal.proto" GrpcServices="Client" Generator="MSBuild:Compile" />
<Content Include="#(Protobuf)" />
<None Remove="#(Protobuf)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DimaRabbitLogger" Version="1.3.3" />
<PackageReference Include="Grpc.AspNetCore.Server" Version="0.1.22-pre1" />
<PackageReference Include="Google.Protobuf" Version="3.8.0" />
<PackageReference Include="Grpc.Tools" Version="1.21.0" PrivateAssets="All" />
<PackageReference Include="Grpc.Core" Version="1.21.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0-preview6.19304.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.0-preview6.19304.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0-preview6.19304.10" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.0.0-preview5" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="System.Runtime.Serialization.Json" Version="4.3.0" />
</ItemGroup>
</Project>
And couple of very simple models:
Model Application:
public class Application
{
int ApplicationId { get; set; }
public string PackageName { get; set; }
public List<WorkspaceApplication> WorkspaceApplications { get; set; }
Model Workspace:
public class Workspace
{
public int WorkspaceId { get; set; }
public string Name { get; set; }
public List<WorkspaceApplication> WorkspaceApplications { get; set; }
}
Class for many-to-many relationship:
public class WorkspaceApplication
{
public int ApplicationId { get; set; }
public Application Application { get; set; }
public string WorkspaceId { get; set; }
public Workspace Workspace { get; set; }
}
And my application context:
public class ApplicationContext : DbContext
{
private readonly string _connectionString;
public DbSet<Workspace> Workspaces { get; set; }
public DbSet<Application> Applications { get; set; }
public ApplicationContext(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("DashboardDb");
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql(_connectionString, b => b.MigrationsAssembly("Dashboard"));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<WorkspaceApplication>()
.HasKey(x => new {x.WorkspaceId, x.ApplicationId});
modelBuilder.Entity<WorkspaceApplication>()
.HasOne(x => x.Workspace)
.WithMany(x => x.WorkspaceApplications)
.HasForeignKey(x => x.WorkspaceId);
modelBuilder.Entity<WorkspaceApplication>()
.HasOne(x => x.Application)
.WithMany(x => x.WorkspaceApplications)
.HasForeignKey(x => x.ApplicationId);
}
}
I run the following console command:
dotnet ef migrations add FirstMigration
and have this error message:
Could not execute because the specified command or file was not found.
Possible cause:
* You have incorrectly typed builtin dotnet.
* You planned to run .NET Core, but dotnet-ef does not exist.
* You wanted to run the global tool, but the PATH specified in the PATH could not find the executable file with the dotnet prefix, which has this name.
This works nice with .Net Core 2.2. Where is the problem?
Starting with 3.0 the dotnet ef is not part of the .NET SDK anymore.
Old behavior
Before 3.0, the dotnet ef tool was included in the .NET Core SDK and was readily available to use from the command line from any project without requiring extra steps.
New behavior
Starting in 3.0, the .NET SDK does not include the dotnet ef tool, so before you can use it you have to explicitly install it as a local or global tool.
To install it, you can run this:
dotnet tool install --global dotnet-ef --version 3.0.0-*
Then you should be able to run normal ef-core commands like dotnet ef migrations add ...
Don't forget to add the path to dotnet tools in the PATH variable of your OS. For example if you use linux ubuntu and zsh as shell you have to add the following int your .zshrc file:
export PATH=$PATH:$HOME/.dotnet/tools
I've have an Asp.Net MVC app in one project and I moved my db context file used to connect to Entity Framework into it's own project, so that I can access EF from both my Asp.Net MVC app and my Azure Function apps. But running the Azure Function throws an exception when trying to get the connection string.
No connection string named 'YogaBandyDatabase' could be found in the application config file.
I tried putting the connection string into the app.config file for the .DataLayer project and I tried putting the connection string into the local.settings.json file and I tried putting the connection string into the portal under application settings connection strings but I'm still getting this exception.
QUESTION - where is it looking for the connection string, it says the application config file? Which one? the one from the .DataLayer project? Did I put it in correctly to the app.config file?
Here is my project structure
Here is the error in the context file
Here is my context file in the .DataLayer project
namespace YogaBandy2017.Context
{
public class YogabandyContext : IdentityDbContext<ApplicationUser>
{
public YogabandyContext()
: base("name=YogaBandyDatabase")
{
}
public YogabandyContext(string connectionString)
: base(connectionString)
{
}
public static YogabandyContext Create()
{
return new YogabandyContext();
}
public DbSet<YogaBandyError> YogaBandyErrors { get; set; }
public DbSet<YogaProfile> YogaProfiles { get; set; }
public DbSet<YogaClass> YogaClasses { get; set; }
public DbSet<YogaSpaceEvent> YogaSpaceEvents { get; set; }
public DbSet<ReportImage> ReportImages { get; set; }
public DbSet<ReportProfile> ReportProfiles { get; set; }
public DbSet<ReportSpace> ReportSpaces { get; set; }
public DbSet<YogaSpace> YogaSpaces { get; set; }
public DbSet<YogaSpaceFollower> YogaSpaceFollower { get; set; }
public DbSet<YogaProfileFollower> YogaProfileFollower { get; set; }
public DbSet<RegisteredStudent> RegisteredStudents { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
}
}
Here is the local.settings.json file with the connection string (maybe syntax is incorrect)
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "the string",
"AzureWebJobsDashboard": "",
"yogabandy2017_RootManageSharedAccessKey_SERVICEBUS": "the string"
},
"ConnectionStrings": {
"YogaBandyDatabase": "the string"
}
}
Here is the connection string in the app.config file for the .DataLayer project
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="YogaBandyDatabase" connectionString="my string" providerName="System.Data.SqlClient" />
<add name="YogaBandyErrorDatabase" connectionString="my string" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v13.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
This one is a little tricky. Log into the Azure portal and navigate to your Function. Click on the Application Settings link on the Overview tab for your Function. Place your EF connection string under the Connection Strings section.
I tried to run code base entity framework migration. And I always get this error (except the initial migration) when run "add-migration" command: Unable to generate an explicit migration because the following explicit migrations are pending: [201607141552034_Add_storeId_firstname_to_customer]. Apply the pending explicit migrations before attempting to generate a new explicit migration. However, if I try to run "update-database -Verbose -ConnectionStringName "ZzaDbConnectionString", I get an very confusing/conflict error: No pending explicit migrations. I tried to delete the migration file then use add-migration to create it again. It only work once. The next time (for example, if I want to add a column to my table), I got the same error. Any suggestion why the problem? Thanks.
EDIT: add code and configuration.
This is Entity class.
namespace Zza.Entities
{
public class Customer
{
public Guid Id { get; set; }
[MaxLength(50)]
public string FullName { get; set; }
}
}
This is Context class:
namespace Zza.Data
{
public class ZzaDbContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
}
}
This is console class:
namespace TestEFMigration
{
public class Program
{
static void Main(string[] args)
{
CreateDataBase();
}
private static void CreateDataBase()
{
var context = new ZzaDbContext();
context.Database.Initialize(false);
}
}
}
context class's app.config
<add name="ZzaDbConnectionString"
connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Zza;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
providerName="System.Data.SqlClient" />
Console's app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<connectionStrings>
<add name="ZzaDbConnectionString" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Zza;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
iceheart