使用npgsql
代码创建表的问题数据库创建应该从版本2.2.0-beta1开始工作: «DavidKarlaš在EF6 +中增加了对EFMigration和数据库创建的支持 现在可以启动Code First项目而无需预先创建数据库。 EntityFramework和Npgsql将负责处理它。 Emil Lenngren添加了对EntityFramework的许多缺失功能的支持。» https://www.nuget.org/packages/Npgsql/2.2.0-beta1
但是,当我尝试这样做时,我遇到了问题。
首先,我做了一个简单的项目,它适用于SqlServer: 我创建了Asp.Net MVC项目(VS2013)并添加了一些代码:
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
}
public class MovieDBContext : DbContext
{
public DbSet<Movie> Movies { get; set; }
}
public class MovieDBInitializer : DropCreateDatabaseIfModelChanges<MovieDBContext>
{
}
public class HomeController : Controller
{
private MovieDBContext db = new MovieDBContext();
public ActionResult Index()
{
List<Movie> objs = db.Movies.ToList();
return View(objs);
}
WebConfig:
<connectionStrings>
<add name="MovieDBContext" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=MovieCreateDbInSql;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\MovieDB.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<contexts>
<context type="MovieCreateDbInSql.Models.MovieDBContext, MovieCreateDbInSql">
<databaseInitializer type="MovieCreateDbInSql.Models.MovieDBInitializer, MovieCreateDbInSql" />
</context>
</contexts>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
启动项目时,将创建数据库MovieDB。
一切正常。
我们可以在项目的App_Data文件夹中看到这个数据库。 好。
然后我尝试用npgsql做同样的事。
EntityFramework6.Npgsql.dll(版本3.1.0.0)
Npgsql.dll(版本3.1.2.0)
2
比改变WebConfig:
<connectionStrings><add name="MovieDBContext" connectionString="Server=127.0.0.1;Port=5432;Database=postgres;User Id=postgres;Password=postgres000;" providerName="Npgsql" /></connectionStrings>
<entityFramework>
<contexts>
<context type="MovieCreateDbInSql.Models.MovieDBContext, MovieCreateDbInSql">
<databaseInitializer type="MovieCreateDbInSql.Models.MovieDBInitializer, MovieCreateDbInSql" />
</context>
</contexts>
<defaultConnectionFactory type="Npgsql.NpgsqlFactory, Npgsql" />
<providers>
<provider invariantName="Npgsql" type="Npgsql.NpgsqlServices, EntityFramework6.Npgsql"></provider>
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="Npgsql" />
<add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql"
type="Npgsql.NpgsqlFactory, Npgsql" />
</DbProviderFactories>
</system.data>
开始。错误:
System.NotSupportedException was unhandled by user code
HResult=-2146233067
Message=Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations.
Source=EntityFramework
但是这个配置对于SqlServer来说已经足够了!
确定。试试这个:
1
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
}
不要真的帮忙。错误是相同的
公共类MovieDBInitializer:DropCreateDatabaseAlways { }
新错误:
Npgsql.PostgresException was unhandled by user code
HResult=-2147467259
Message=55006: база данных "postgres" занята другими пользователями
Source=Npgsql
ErrorCode=-2147467259
BaseMessage=база данных "postgres" занята другими пользователями
Code=55006
Detail=Эта база данных используется ещё в 1 сеансе.
(error 55006 database is being accessed by other user)
这个错误也不好。 据我所知这个错误是因为我们有一个严重的数据库posgresql不像原始的localdb.sql。 在postgresql中删除db操作并不像在localdb.sql中那么容易。
我找到了关于该错误的几个链接:
https://groups.google.com/forum/#!topic/npgsql-help/1f5niOiHpGg
Drop a database being accessed by another users?
npgsql and Entity Framework code first setup problems
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<MovieDBContext>(null);
}
再次出现同样的错误:
System.NotSupportedException was unhandled by user code
HResult=-2146233067
Message=Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations.
Source=EntityFramework
我应该怎样做才能有机会通过代码优先模型创建表?
当然我可以在SqlServer中生成数据库,而不是将脚本转换为postgresql,但我想用npgsql来做这个。
答案 0 :(得分:1)
我使用的库:
我的数据库上下文:
public class CustomContext : DbContext
{
public CustomContext()
: base("name=CustomContext")
{
Database.SetInitializer(
new MigrateDatabaseToLatestVersion<CustomContext, Configuration>());
}
public DbSet<Movie> Movies { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Change schema name from "dbo" => "public" for all entities (except MigrationHistory).
// MigrationHistory schema name is modified in custom HistoryContext
modelBuilder.Types().Configure(c => c.ToTable(c.ClrType.Name, "public"));
}
}
迁移历史记录表的默认架构设置为&#34; dbo&#34;。如果你想让它在不同的模式(例如public)中,你必须创建一个自定义的HistoryContext。
目前用 modelBuilder.HasDefaultSchema(&#34)设置默认模式是不可能的。 ;公共&#34;),同时使用自动迁移(AFAIK)。
public class CustomHistoryContext : HistoryContext
{
public CustomHistoryContext(DbConnection existingConnection, string defaultSchema)
: base(existingConnection, defaultSchema)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Change schema from "dbo" to "public"
modelBuilder.Entity<HistoryRow>()
.ToTable(tableName: "__MigrationHistory",
schemaName: "public");
}
}
最后,我的迁移配置类如下所示:
internal sealed class Configuration : DbMigrationsConfiguration<CustomContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
// Setting custom historyContext factory.
// Used for modify __MigrationHistory table schema name from "dbo" to "public"
this.SetHistoryContextFactory("Npgsql",
(connection, defaultSchema) =>
new CustomHistoryContext(connection, defaultSchema));
}
protected override void Seed(CustomContext context)
{
// This method will be called after migrating to the latest version.
}
}
完成这些步骤后,自动代码首次迁移才能正常运行。
答案 1 :(得分:0)
但是,这里有更多细节。
我有课程:
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime IssueDay { get; set; }
public decimal EarnedMoney { get; set; }
public virtual ICollection<Actor> Actors { get; set; }
}
public class Actor
{
public int ID { get; set; }
public int MovieID { get; set; }
public DateTime BirthDay { get; set; }
public string Name { get; set; }
}
我得到了脚本:
CREATE TABLE "Movie"
(
"ID" serial NOT NULL,
"Title" text,
"IssueDay" timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00'::timestamp without time zone,
"EarnedMoney" numeric(18,2) NOT NULL DEFAULT 0,
CONSTRAINT "PK_public.Movie" PRIMARY KEY ("ID")
)
WITH (
OIDS=FALSE
);
ALTER TABLE "Movie"
OWNER TO postgres;
CREATE TABLE "Actor"
(
"ID" serial NOT NULL,
"MovieID" integer NOT NULL DEFAULT 0,
"Name" text,
"BirthDay" timestamp without time zone NOT NULL DEFAULT '0001-01-01 00:00:00'::timestamp without time zone,
CONSTRAINT "PK_public.Actor" PRIMARY KEY ("ID"),
CONSTRAINT "FK_public.Actor_public.Movie_MovieID" FOREIGN KEY ("MovieID")
REFERENCES "Movie" ("ID") MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE CASCADE
)
WITH (
OIDS=FALSE
);
ALTER TABLE "Actor"
OWNER TO postgres;
CREATE INDEX "Actor_IX_MovieID"
ON "Actor"
USING btree
("MovieID");
这些脚本当然需要额外的处理。
这就是为什么一般情况下直接在postgres中生成脚本或在sqlServer中生成然后通过Navicat转换为postgres没有区别...