【问题标题】:How to add migrations for Entity Framework in a Xamarin Forms project?如何在 Xamarin Forms 项目中为实体框架添加迁移?
【发布时间】:2021-05-11 21:33:28
【问题描述】:

我正在尝试让 EF 迁移在 Xamarin Forms 项目中工作。我有一个用于 SQLite 数据库的 DbContext:

    public class TestDbContext : DbContext
    {
        public DbSet<Item> Items { get; set; }

        public TestDbContext()
        {
            SQLitePCL.Batteries_V2.Init();

            this.Database.EnsureCreated();
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            string dbPath = Path.Combine(FileSystem.AppDataDirectory, "testDb.db3");

            optionsBuilder
                .UseSqlite($"Filename={dbPath}");
        }
    }

我为标准库安装了Microsoft.EntityFrameworkCore.Tools nuget,但它不起作用。从this开始,我添加了一个Dummy.NET Core项目。

  1. 我在 Dummy(Xamarin Forms 项目)中引用了 .NET Standard 库 (2.1)
  2. 我也将Microsoft.EntityFrameworkCore.SqliteMicrosoft.EntityFrameworkCore.Tools nuget 包安装到了虚拟项目中
  3. 我在 .net 标准库中实现了一个IDesignTimeDbContextFactory,如下所示:
    public class DesignTimeFactory : IDesignTimeDbContextFactory<TestDbContext>
    {
        public TestDbContext CreateDbContext(string[] args)
        {
            return new TestDbContext();
        }
    }

当我运行命令PM&gt; Add-Migration InitialCreate -P XamarinEFTest -S EFDummy 时出现异常:

Build started...
Build succeeded.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> Xamarin.Essentials.NotImplementedInReferenceAssemblyException: This functionality is not implemented in the portable version of this assembly. You should reference the NuGet package from your main application project in order to reference the platform-specific implementation.
   at Xamarin.Essentials.FileSystem.get_PlatformAppDataDirectory()
   at Xamarin.Essentials.FileSystem.get_AppDataDirectory()
   at XamarinEFTest.TestDbContext.OnConfiguring(DbContextOptionsBuilder optionsBuilder) in C:\Users\szabk\source\repos\XamarinEFTest\XamarinEFTest\XamarinEFTest\TestDbContext.cs:line 24
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.get_Dependencies()
   at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureCreated()
   at XamarinEFTest.TestDbContext..ctor() in C:\Users\szabk\source\repos\XamarinEFTest\XamarinEFTest\XamarinEFTest\TestDbContext.cs:line 19
   at XamarinEFTest.DesignTimeFactory.CreateDbContext(String[] args) in C:\Users\szabk\source\repos\XamarinEFTest\XamarinEFTest\XamarinEFTest\DesignTimeFactory.cs:line 12
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContextFromFactory(Type factory, Type contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass16_0.<FindContextFactory>b__1()
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Exception has been thrown by the target of an invocation.

我有 VS 2019 16.8.4,我使用滑块菜单从布局模板创建了测试 xamarin 项目。

我需要做什么?

编辑:也许我需要使用不同的 SQLite 驱动程序和不同的 DesignTimeFactory 设置核心项目?但这将如何运作?我最终需要迁移才能在手机中工作。

【问题讨论】:

    标签: xamarin xamarin.forms entity-framework-core entity-framework-migrations


    【解决方案1】:

    Xamarin.Essentials FileSystem.AppDataDirectory 在您尝试创建迁移的 Windows/Mac 上不起作用。

    使用这个 sqlite 数据库路径来创建迁移:

    optionsBuilder.UseSqlite($"Data Source=migrations.db3");
    

    这个路径是相对的,你最终会在你的项目文件夹中创建一个migrations.db3 文件。忽略 .db 文件,它的唯一目的是创建迁移。

    编辑: 我一直在我的应用程序中使用这个 DbContext,它工作得很好。

    public class MyDbContext : DbContext
    {
        private string _databasePath;
    
        public DbSet<MyEntity> Issues { get; set; }
    
        [Obsolete("Don't use this for production. This is only for creating migrations.")]
        public MyDbContext() : this("nothing.db")
        {
    
        }
    
        public MyDbContext(string dbPath)
        {
            _databasePath = dbPath;
        }
    
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlite($"Data Source={_databasePath}");
            }
        }
    }
    

    【讨论】:

    • 我更改了代码,只是为了生成迁移,但它给了我同样的异常。
    • 异常意味着您仍在某处调用FileSystem.AppDataDirectory。这在 Xamarin.Forms 平台特定项目之外不起作用。确保在创建迁移时没有调用它。我还在我的答案中添加了一个工作示例。
    • 谢谢。看起来我在第一次初始化上下文时调用了它。现在可以了。
    • 太棒了!喜欢听。
    猜你喜欢
    • 1970-01-01
    • 2018-11-17
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 2019-02-25
    相关资源
    最近更新 更多