实体框架数据库连接问题(Entity Framework database connection question)
我们正在使用
.Net Entity Framework
来完成与数据库相关的工作。 我们的数据库是Sybase SQL Anywhere
。using (AndeDBEntities db = new AndeDBEntities(decryptConnStr())) { }
我们使用大量上述语句来访问数据库。 我的问题是,我们是否需要在访问完成后每次关闭连接以及如何执行此操作?
有一次我看到“超出数据库服务器连接限制”错误。 我想知道我们的数据库连接代码一定有问题。
We are using
.Net Entity Framework
to do our database related work. Our database isSybase SQL Anywhere
.using (AndeDBEntities db = new AndeDBEntities(decryptConnStr())) { }
We use a lots of above statements to access database. My questions are do we need to close the connection each time after the access is done and how to do that?
At one time I saw "Database server connection limit exceeded" error. I am wondering there must be something wrong in our database connection code.
原文:https://stackoverflow.com/questions/3150565
最满意答案
这是一个艰难的转变,我建议用两遍来表演。
首先,将
DriverId
FK保留在DriverWork
,并使DriverId
中的WorkPage
可选(可为空):public class WorkPage { [Key] public int Id { get; set; } public byte CommissionPercentage { get; set; } public bool IsClosed { get; set; } public DateTime? DateClosed { get; set; } public int? DriverId { get; set; } [ForeignKey(nameof(DriverId))] public Driver Driver { get; set; } } public class DriverWork { [Key] public int Id { get; set; } public string FromLocation { get; set; } public string ToLocation { get; set; } public int Price { get; set; } public DateTime Date { get; set; } public int DriverId { get; set; } [ForeignKey(nameof(DriverId))] public Driver Driver { get; set; } public int WorkPageId { get; set; } [ForeignKey(nameof(WorkPageId))] public WorkPage WorkPage { get; set; } }
生成新的迁移。 它应该是这样的:
public override void Up() { CreateTable( "dbo.WorkPage", c => new { Id = c.Int(nullable: false, identity: true), CommissionPercentage = c.Byte(nullable: false), IsClosed = c.Boolean(nullable: false), DateClosed = c.DateTime(), DriverId = c.Int(nullable: false), }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.Driver", t => t.DriverId, cascadeDelete: true) .Index(t => t.DriverId); AddColumn("dbo.DriverWork", "WorkPageId", c => c.Int()); CreateIndex("dbo.DriverWork", "WorkPageId"); AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id"); }
执行迁移。 然后通过从
DriverWork
删除Driver
并在DriverId
中WorkPage
(非null)来恢复所需的实体模型:public class WorkPage { [Key] public int Id { get; set; } public byte CommissionPercentage { get; set; } public bool IsClosed { get; set; } public DateTime? DateClosed { get; set; } public int DriverId { get; set; } [ForeignKey(nameof(DriverId))] public Driver Driver { get; set; } } public class DriverWork { [Key] public int Id { get; set; } public string FromLocation { get; set; } public string ToLocation { get; set; } public int Price { get; set; } public DateTime Date { get; set; } public int WorkPageId { get; set; } [ForeignKey(nameof(WorkPageId))] public WorkPage WorkPage { get; set; } }
生成第二个新迁移。 它应该看起来像这样:
public override void Up() { DropForeignKey("dbo.DriverWork", "DriverId", "dbo.Driver"); DropForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPages"); DropIndex("dbo.DriverWork", new[] { "DriverId" }); DropIndex("dbo.DriverWork", new[] { "WorkPageId" }); AlterColumn("dbo.DriverWork", "WorkPageId", c => c.Int(nullable: false)); CreateIndex("dbo.DriverWork", "WorkPageId"); AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id", cascadeDelete: true); DropColumn("dbo.DriverWork", "DriverId"); }
使用
Sql
方法填充WorkPage
表数据并在需要之前更新WorkTableId
FK。 例如,在Up
方法的开头插入以下内容:Sql(@"insert into dbo.WorkPage (CommissionPercentage, IsClosed, DateClosed, DriverId) select 0, 0, null, DriverId from dbo.DriverWork"); Sql(@"update dbo.DriverWork set WorkPageId = WP.Id from dbo.DriverWork DW join dbo.WorkPage WP on DW.DriverId = WP.DriverId");
执行迁移,您就完成了。
实际上,
Sql
调用哪些转换数据可以在第一次迁移Up
方法的末尾。事先了解所有这些,您可以按原样保留新模型(跳过第一步),只需将生成的迁移
Up
方法替换为上述两者的并集,例如public override void Up() { CreateTable( "dbo.WorkPage", c => new { Id = c.Int(nullable: false, identity: true), CommissionPercentage = c.Byte(nullable: false), IsClosed = c.Boolean(nullable: false), DateClosed = c.DateTime(), DriverId = c.Int(nullable: false), }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.Driver", t => t.DriverId, cascadeDelete: true) .Index(t => t.DriverId); AddColumn("dbo.DriverWork", "WorkPageId", c => c.Int()); CreateIndex("dbo.DriverWork", "WorkPageId"); AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id"); Sql(@"insert into dbo.WorkPage (CommissionPercentage, IsClosed, DateClosed, DriverId) select 0, 0, null, DriverId from dbo.DriverWork"); Sql(@"update dbo.DriverWork set WorkPageId = WP.Id from dbo.DriverWork DW join dbo.WorkPage WP on DW.DriverId = WP.DriverId"); DropForeignKey("dbo.DriverWork", "DriverId", "dbo.Driver"); DropForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPages"); DropIndex("dbo.DriverWork", new[] { "DriverId" }); DropIndex("dbo.DriverWork", new[] { "WorkPageId" }); AlterColumn("dbo.DriverWork", "WorkPageId", c => c.Int(nullable: false)); CreateIndex("dbo.DriverWork", "WorkPageId"); AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id", cascadeDelete: true); DropColumn("dbo.DriverWork", "DriverId"); }
Sine it's a tough transformation, I would suggest performing it with two passes.
First, keep the
DriverId
FK in theDriverWork
and makeDriverId
inWorkPage
optional (nullable):public class WorkPage { [Key] public int Id { get; set; } public byte CommissionPercentage { get; set; } public bool IsClosed { get; set; } public DateTime? DateClosed { get; set; } public int? DriverId { get; set; } [ForeignKey(nameof(DriverId))] public Driver Driver { get; set; } } public class DriverWork { [Key] public int Id { get; set; } public string FromLocation { get; set; } public string ToLocation { get; set; } public int Price { get; set; } public DateTime Date { get; set; } public int DriverId { get; set; } [ForeignKey(nameof(DriverId))] public Driver Driver { get; set; } public int WorkPageId { get; set; } [ForeignKey(nameof(WorkPageId))] public WorkPage WorkPage { get; set; } }
Generate new migration. It should be something like this:
public override void Up() { CreateTable( "dbo.WorkPage", c => new { Id = c.Int(nullable: false, identity: true), CommissionPercentage = c.Byte(nullable: false), IsClosed = c.Boolean(nullable: false), DateClosed = c.DateTime(), DriverId = c.Int(nullable: false), }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.Driver", t => t.DriverId, cascadeDelete: true) .Index(t => t.DriverId); AddColumn("dbo.DriverWork", "WorkPageId", c => c.Int()); CreateIndex("dbo.DriverWork", "WorkPageId"); AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id"); }
Execute the migration. Then restore the desired entity model by removing the
Driver
fromDriverWork
and makingDriverId
inWorkPage
required (non null):public class WorkPage { [Key] public int Id { get; set; } public byte CommissionPercentage { get; set; } public bool IsClosed { get; set; } public DateTime? DateClosed { get; set; } public int DriverId { get; set; } [ForeignKey(nameof(DriverId))] public Driver Driver { get; set; } } public class DriverWork { [Key] public int Id { get; set; } public string FromLocation { get; set; } public string ToLocation { get; set; } public int Price { get; set; } public DateTime Date { get; set; } public int WorkPageId { get; set; } [ForeignKey(nameof(WorkPageId))] public WorkPage WorkPage { get; set; } }
Generate a second new migration. It should look something like this:
public override void Up() { DropForeignKey("dbo.DriverWork", "DriverId", "dbo.Driver"); DropForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPages"); DropIndex("dbo.DriverWork", new[] { "DriverId" }); DropIndex("dbo.DriverWork", new[] { "WorkPageId" }); AlterColumn("dbo.DriverWork", "WorkPageId", c => c.Int(nullable: false)); CreateIndex("dbo.DriverWork", "WorkPageId"); AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id", cascadeDelete: true); DropColumn("dbo.DriverWork", "DriverId"); }
Use
Sql
methods to populate theWorkPage
table data and update theWorkTableId
FK before making it required. For instance, insert the following at the beginning of theUp
method:Sql(@"insert into dbo.WorkPage (CommissionPercentage, IsClosed, DateClosed, DriverId) select 0, 0, null, DriverId from dbo.DriverWork"); Sql(@"update dbo.DriverWork set WorkPageId = WP.Id from dbo.DriverWork DW join dbo.WorkPage WP on DW.DriverId = WP.DriverId");
Execute the migration and you are done.
Actually the
Sql
calls which transform the data can be at the end of the first migrationUp
method.Knowing all that in advance, you can keep your new model as is (skip the first step) and simply replace the generated migration
Up
method with the union of the above two, e.g.public override void Up() { CreateTable( "dbo.WorkPage", c => new { Id = c.Int(nullable: false, identity: true), CommissionPercentage = c.Byte(nullable: false), IsClosed = c.Boolean(nullable: false), DateClosed = c.DateTime(), DriverId = c.Int(nullable: false), }) .PrimaryKey(t => t.Id) .ForeignKey("dbo.Driver", t => t.DriverId, cascadeDelete: true) .Index(t => t.DriverId); AddColumn("dbo.DriverWork", "WorkPageId", c => c.Int()); CreateIndex("dbo.DriverWork", "WorkPageId"); AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id"); Sql(@"insert into dbo.WorkPage (CommissionPercentage, IsClosed, DateClosed, DriverId) select 0, 0, null, DriverId from dbo.DriverWork"); Sql(@"update dbo.DriverWork set WorkPageId = WP.Id from dbo.DriverWork DW join dbo.WorkPage WP on DW.DriverId = WP.DriverId"); DropForeignKey("dbo.DriverWork", "DriverId", "dbo.Driver"); DropForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPages"); DropIndex("dbo.DriverWork", new[] { "DriverId" }); DropIndex("dbo.DriverWork", new[] { "WorkPageId" }); AlterColumn("dbo.DriverWork", "WorkPageId", c => c.Int(nullable: false)); CreateIndex("dbo.DriverWork", "WorkPageId"); AddForeignKey("dbo.DriverWork", "WorkPageId", "dbo.WorkPage", "Id", cascadeDelete: true); DropColumn("dbo.DriverWork", "DriverId"); }
相关问答
更多-
实体框架4的示例:将POCO映射到EAV数据库?(Examples for Entity Framework 4: Mapping POCOs to EAV database?)[2023-02-11]
EAV表格通常是一项混乱的业务,Joe Celko( 避免EAV销毁 )和其他许多行业专家(例如, 您应该避免的五个简单数据库设计错误 )合理地警告不要使用EAV构造。 抛开所有的数据库批评者:基于这样的EAV的.NET中的对象如何看起来像? 它可以具有任何类型的任何数量的属性,所以基本上,它必须是一个“通用”对象,几乎可以呈现任何形状。 这个想法让我的皮肤爬行并违背了强类型语言的最基本概念 - 是的,你可以像Ruby和Python这样的动态语言来做类似的事情,但在C#中呢? 唯一可行的选择可能会与.NET ... -
模拟实体框架数据库(Mock Entity Framework database)[2023-11-12]
转到此链接并查看本节“在自动创建的数据库中播种初始数据” http://weblogs.asp.net/scottgu/archive/2010/07/16/code-first-development-with-entity-framework-4.aspx Goto this link and have a look at this section "Seeding Initial Data in Automatically Created Databases" http://weblogs.asp.n ... -
这是一个艰难的转变,我建议用两遍来表演。 首先,将DriverId FK保留在DriverWork ,并使DriverId中的WorkPage可选(可为空): public class WorkPage { [Key] public int Id { get; set; } public byte CommissionPercentage { get; set; } public bool IsClosed { get; set; } public DateTi ...
-
如何使用Entity Framework提高数据库插入性能(How to increase database insert performance with Entity Framework)[2021-09-30]
使用SQL Compact Bulk Insert Library库在批量中插入数据。 如果您需要更新任何记录,请使用以下技巧: 在数据库中创建一个临时表 使用库来批量插入登台表 然后通过读取登台表并更新目标表的记录来执行存储过程来执行更新。 Use SQL Compact Bulk Insert Library library to insert the data in bulks. If you need to update any records, then use this technique: C ... -
现在我有下一个解决方案。 在main方法或global.asax中是这样的: var migration_config = new Configuration(); migration_config.TargetDatabase = new DbConnectionInfo("BlogContext"); var migrator = new DbMigrator(migration_config); migrator.Update(); migration_conf ...
-
它会在您更改连接字符串时起作用。 我建议您在创建新的'ADO.NET实体数据模型'时使用VS添加新项目来选择'Code First from database'。 It will work when you change the connection string. I recommend you select the 'Code First from database' when creating new 'ADO.NET Entity Data Model' with VS add new item.
-
使用Entity Framework在运行时更改数据库结构?(Changing database structure at runtime with Entity Framework?)[2023-03-02]
您可以使用代码优先模型使用EF 4执行此操作。 也就是说,我倾向于避免在有或没有EF的情况下动态更改数据库元数据。 相反,我会选择一个适合用户不断变化的需求的架构。 You can do this with EF 4 using a code-first model. That said, I tend to avoid changing DB metadata on the fly, with or without EF. Rather, I'd choose a schema which fits th ... -
它可能是您的实体框架的不同版本,但这些连接字符串中似乎缺少某些东西,我看起来像这样: connectionString="metadata=res://*/xxx.csdl|res://*/xxx.ssdl|res://*/xxx.msl;provider=System.Data.SqlClient;provider connection string="data source=xxx;initial catalog=xxx;integrated security=True;multipleac ...
-
是的,有办法。 使用实体框架迁移。 从包管理器控制台执行此操作开始: Enable-Migrations 这是一篇关于MSDN的文章 。 只有在使用“实体框架代码优先”方法时,才可以选择使用迁移。 EF迁移的一个很酷的事情是您可以启用自动迁移选项。 基本上,所有不会影响数据完整性或丢失的架构更改(例如,在数据库中添加列或新表)都可以自动推送,而无需显式实现迁移。 Yes, there is a way. Use Entity Framework migrations. Start from executi ...
-
我只是在您发送数据库位置的数据库上下文中声明另一个构造函数。 public DatabaseContext(string connection) : base(connection) { } 注意对base() (基类构造函数base()的调用。 根据EF Spec ,您可以传入 与数据库的现有连接 .config中包含的连接字符串的名称 连接字符串 希望这可以帮助。 I would just declare another constructor on your database context wh ...