iT邦幫忙

1

C# 關於 Code-First 進行移轉 資料庫 問題

您好:
我使用 VisualStudio 2019 建立一個 .NetFramework 4.8 的程式庫專案。
整個專案 只有 ContextT1 , T1 這兩個 Class,內容如下:
[T1類別]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data.Entity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ModelsForNetFW
{
    public class T1
    {
        [Key]
        public int DID { get; set; }
        public string F1 { get; set; }
        public DateTime F2 { get; set; }
    }
}

[ContextT1 類別]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data.Entity;
using System.Data.Entity.SqlServer;

namespace ModelsForNetFW
{
    public class ContextT1 : DbContext
    {
        public DbSet<T1> T1s { get; set; }

        public ContextT1() : base("ContextT1")
        {

        }
    }
}

System.Data.Entity 的版本是 6.0.0.0 版。

當我在 套件管理主控台 執行 Enable-Migrations 卻出現 :
"Unable to load the specified metadata resource"
這一個錯誤訊息,完整內容如下:

PM> Enable-Migrations
Checking if the context targets an existing database...
System.Data.Entity.Core.MetadataException: Unable to load the specified metadata resource.
   於 System.Data.Entity.Core.Metadata.Edm.MetadataArtifactLoaderCompositeResource.LoadResources(String assemblyName, String resourceName, ICollection`1 uriRegistry, MetadataArtifactAssemblyResolver resolver)
   於 System.Data.Entity.Core.Metadata.Edm.MetadataArtifactLoaderCompositeResource.CreateResourceLoader(String path, ExtensionCheck extensionCheck, String validExtension, ICollection`1 uriRegistry, MetadataArtifactAssemblyResolver resolver)
   於 System.Data.Entity.Core.Metadata.Edm.MetadataCache.SplitPaths(String paths)
   於 System.Data.Entity.Core.Common.Utils.Memoizer`2.Result.GetValue()
   於 System.Data.Entity.Core.Common.Utils.Memoizer`2.Evaluate(TArg arg)
   於 System.Data.Entity.Core.Metadata.Edm.MetadataCache.GetArtifactLoader(DbConnectionOptions effectiveConnectionOptions)
   於 System.Data.Entity.Core.Metadata.Edm.MetadataCache.GetMetadataWorkspace(DbConnectionOptions effectiveConnectionOptions)
   於 System.Data.Entity.Core.EntityClient.EntityConnection.GetMetadataWorkspace()
   於 System.Data.Entity.Core.Objects.ObjectContext..ctor(EntityConnection connection, Boolean isConnectionConstructor, ObjectQueryExecutionPlanFactory objectQueryExecutionPlanFactory, Translator translator, ColumnMapFactory columnMapFactory)
   於 System.Data.Entity.Internal.InternalConnection.CreateObjectContextFromConnectionModel()
   於 System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   於 System.Data.Entity.Internal.LazyInternalContext.get_ModelBeingInitialized()
   於 System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer)
   於 System.Data.Entity.Utilities.DbContextExtensions.GetModel(Action`1 writeXml)
   於 System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext, DatabaseExistenceState existenceState, Boolean calledByCreateDatabase)
   於 System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
   於 System.Data.Entity.Migrations.Design.MigrationScaffolder..ctor(DbMigrationsConfiguration migrationsConfiguration)
   於 System.Data.Entity.Infrastructure.Design.Executor.CreateMigrationScaffolder(DbMigrationsConfiguration configuration)
   於 System.Data.Entity.Infrastructure.Design.Executor.ScaffoldInitialCreateInternal(DbConnectionInfo connectionInfo, String contextTypeName, String contextAssemblyName, String migrationsNamespace, Boolean auto, String migrationsDir)
   於 System.Data.Entity.Infrastructure.Design.Executor.ScaffoldInitialCreate.<>c__DisplayClass0_0.<.ctor>b__0()
   於 System.Data.Entity.Infrastructure.Design.Executor.OperationBase.<>c__DisplayClass4_0`1.<Execute>b__0()
   於 System.Data.Entity.Infrastructure.Design.Executor.OperationBase.Execute(Action action)
Unable to load the specified metadata resource.

因為 我是直接建立 Class , 並沒有使用 VS 裡面的 ADO.NET 實體模型 範本,
我的想法是 單純建立 Class 然後透過 Enable-Migrations 指令直接對資料庫做建立 T1 資料表。
這個思路有錯誤嗎? 因為我有查到有人這樣成功的範例,但是奇怪的是,我只要對這個專案執行 Enable-Migrations
就會出現我上述的錯誤。
我在執行 Enable-Migrations 的時候,在 套件管理主控台 的視窗有指定預設 這個專案。

  後端資料庫是 MS-SQL Server 2019 Developer 版。

  我有檢查過 App.Config 裡的 connectionStrings 標籤,設定的 連線字串拿到另一個 Window Form 是可以正常連線到資料庫的,而且在 WinForm 用這個連線字串可以建立資料表。

  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>
  <connectionStrings>
    <add name="ContextT1" 
         connectionString="Server=192.168.10.11;Database=TESTDB;User Id=UAdmin;Password=@2021A03b18c@;multipleactiveresultsets=True;application name=EntityFramework" 
         providerName="System.Data.SqlClient" />

  </connectionStrings>
  <entityFramework>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer"/>
    </providers>
  </entityFramework>
</configuration>
  懇請大家幫忙我看看是哪邊出問題了,感謝。

1 個回答

1
japhenchen
iT邦大師 1 級 ‧ 2021-03-19 08:15:12

參考這一段看看

This little change help with this problem.

I have Solution with 3 project.

connectionString="metadata=res://*/Model.Project.csdl|res://*/Model.Project.ssdl|res://*/Model.Project.msl;
change to

connectionString="metadata=res://*/;

感謝大家回應,我目前有查到是我在 VS 裡的套件管理器主控台下的指令需要增加參數如下給大家參考看看:

Enable-Migrations
PM> Enable-Migrations -ContextTypeName "DbEntities" -ProjectName "DAL" -StartUpProjectName "Groving" -ConnectionStringName "DBEntities" -Verbose

Add-Migration
PM> Add-Migration -Name "20180719_V1" -ProjectName "DAL" -StartUpProjectName "DAL" -ConnectionStringName "DBEntities" -Verbose

Update-Database
PM> Update-Database -ProjectName "DAL" -StartUpProjectName "DAL" -ConnectionStringName "DBEntities" -Verbose

ContextTypeName:專案繼承自DBContext的類別名字。
EnableAutomaticMigrations:開啟自動遷移。
ProjectName:存放DBContext類別的項目專案。
StartUpProjectName:方案中啟動DBContext項目的專案,作用是使用該專案下的連接字串。
ConnectionStringName:連接字串名稱

參考 邦友 Teddie Hsiung 的文章
Code-First 多個專案下的方案的Migration寫法

目前我用 邦友 Teddie Hsiung的方式可以正常的從 Code-First 類別更新到資料庫,不用在連結字串中指定任何的 中繼資料檔 (CSDL , SSDL , MSL),非常好用。

我要發表回答

立即登入回答