【问题标题】:'No such table' after Deploying ASP.Net Core API with SQLite DB on Linux在 Linux 上使用 SQLite DB 部署 ASP.Net Core API 后出现“没有这样的表”
【发布时间】:2023-03-21 06:43:01
【问题描述】:

更新:我能够在根路径中找到measurements.db 文件。它没有像错误消息所说的那样有一个测量表,这可能会导致它。

用我的本地文件替换它 - 修复它并且程序按预期工作。

所以我的问题发生了变化:为什么它不在 db 文件中创建测量表?


你好,

首先项目在本地运行良好!我遇到的问题是,在发布后(使用命令dotnet publish -c Release -r debian-x64),将发布文件夹的文件移动到 Linux VM 并使用dotnet MessdatenController.ddl 启动它无法自行创建measurements.db 文件,这很可能导致以下错误。 (手动添加/上传时也找不到它)。

info: Microsoft.Hosting.Lifetime[0]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://IP.OF.LINUX.VM/api/Measurements/GetMeasurements
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'MessdatenController.Controllers.MeasurementsController.GetMeasurements (MessdatenController)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
      Route matched with {action = "GetMeasurements", controller = "Measurements"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.ActionResult`1[System.Collections.Generic.IEnumerable`1[MessdatenController.Models.Measurement]] GetMeasurements() on controller MessdatenController.Controllers.MeasurementsController (MessdatenController).
info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 3.1.9 initialized 'MeasurementsContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: None
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (21ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT "m"."MeasurementId", "m"."PM10", "m"."PM25", "m"."Posted", "m"."Timestamp"
      FROM "Measurements" AS "m"
      ORDER BY "m"."Timestamp"
fail: Microsoft.EntityFrameworkCore.Query[10100]
      An exception occurred while iterating over the results of a query for context type 'MessdatenController.Business.MeasurementsContext'.
      Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: Measurements'.
         at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
         at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements(Stopwatch timer)+MoveNext()
         at Microsoft.Data.Sqlite.SqliteCommand.GetStatements(Stopwatch timer)+MoveNext()
         at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
         at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
         at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior)
         at System.Data.Common.DbCommand.ExecuteReader()
         at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
         at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.InitializeReader(DbContext _, Boolean result)
         at Microsoft.EntityFrameworkCore.Storage.Internal.NoopExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
         at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: Measurements'.
   at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
   at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements(Stopwatch timer)+MoveNext()
   at Microsoft.Data.Sqlite.SqliteCommand.GetStatements(Stopwatch timer)+MoveNext()
   at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
   at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
   at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader()
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.InitializeReader(DbContext _, Boolean result)
   at Microsoft.EntityFrameworkCore.Storage.Internal.NoopExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
      Executed action MessdatenController.Controllers.MeasurementsController.GetMeasurements (MessdatenController) in 1061.5466ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'MessdatenController.Controllers.MeasurementsController.GetMeasurements (MessdatenController)'
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HM4PTAT76L67", Request id "0HM4PTAT76L67:00000001": An unhandled exception was thrown by the application.
Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: Measurements'.
   at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
   at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements(Stopwatch timer)+MoveNext()
   at Microsoft.Data.Sqlite.SqliteCommand.GetStatements(Stopwatch timer)+MoveNext()
   at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
   at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
   at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.ExecuteReader()
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.InitializeReader(DbContext _, Boolean result)
   at Microsoft.EntityFrameworkCore.Storage.Internal.NoopExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at MessdatenController.Controllers.MeasurementsController.GetMeasurements() in C:\Users\michu\Desktop\Wissenschaftspreis-2021\MessdatenController\MessdatenController\Controllers\MeasurementsController.cs:line 23
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 1312.107ms 500

通过 Apache 的路由应该可以正常工作,因为如果到达控制器方法。

现在关于我的文件:

Program.cs 保持默认。

Startup.cs

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<MeasurementsContext>(options => options.UseSqlite("Data Source=measurements.db"));

            services.AddTransient<IMeasurementsService, MeasurementsService>();

            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
    
            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }

Measurement.cs

public class Measurement
    {
        public Measurement(PostMeasurement pm, DateTime posted)
        {
            this.Timestamp = pm.Timestamp;
            this.PM10 = pm.PM10;
            this.PM25 = pm.PM25;
            this.Posted = posted;
        }

        public Measurement(Guid measurementId, DateTime timestamp, double pM10, double pM25, DateTime posted)
        {
            MeasurementId = measurementId;
            Timestamp = timestamp;
            PM10 = pM10;
            PM25 = pM25;
            Posted = posted;
        }

        public Guid MeasurementId { get; set; }

        public DateTime Timestamp { get; set; }

        public Double PM10 { get; set; }

        public Double PM25 { get; set; }

        public DateTime Posted { get; set; }
    }

MeasurementsContext.cs:

public class MeasurementsContext : DbContext
    {
        public MeasurementsContext(DbContextOptions<MeasurementsContext> options) : base(options)
        { }
        public DbSet<Measurement> Measurements { get; set; }
    }
}

服务

public interface IMeasurementsService
    {
        public Measurement AddMeasurement(PostMeasurement measurement, DateTime posted);
        public ICollection<Measurement> AddMeasurements(IEnumerable<PostMeasurement> measurements, DateTime posted);
        public IQueryable<Measurement> GetAllMeasurements();
        public IQueryable<Measurement> GetMeasurementsBetweenTimestamps(DateTime start, DateTime end);
    }

它的实现

public class MeasurementsService : IMeasurementsService
    {
        private readonly MeasurementsContext _context;

        public MeasurementsService(MeasurementsContext context)
        {
            _context = context;
        }

        public Measurement AddMeasurement(PostMeasurement measurement, DateTime posted)
        {
            Measurement m = new Measurement(measurement, posted);
            _context.Add(m);
            _context.SaveChanges();

            return m;
        }

        public ICollection<Measurement> AddMeasurements(IEnumerable<PostMeasurement> measurements, DateTime posted)
        {
            List<Measurement> result = new List<Measurement>();

            foreach (PostMeasurement postM in measurements)
            {
                Measurement tempM = new Measurement(postM, posted);
                _context.Add(tempM);
                result.Add(tempM);
            }
            _context.SaveChanges();

            return result;
        }

        public IQueryable<Measurement> GetAllMeasurements()
        {
            return _context.Measurements.OrderBy(m => m.Timestamp);
        }

        public IQueryable<Measurement> GetMeasurementsBetweenTimestamps(DateTime start, DateTime end)
        {
            return _context.Measurements.Where(r => r.Timestamp > start && r.Timestamp < end).OrderBy(m => m.Timestamp);
        }

    }

在查看我的问题时,我省略了控制器,因为它不应该很重要。

感谢您的任何建议,并随时问我任何问题 - 我会尽快回复

【问题讨论】:

    标签: c# sqlite api asp.net-core deployment


    【解决方案1】:

    EntityFramework 的 SQLite 提供程序不会自动为您创建数据库或添加缺失的表。如果数据库文件不存在,您可以调用dbContext.Database.EnsureCreatedAsync() 让EF 创建数据库文件。然后它还将创建所有必需的表。但是,如果文件已经存在,则不会对其进行修改。

    如果您以后想在数据库中添加其他表,您应该考虑使用migrations,它允许您随着时间的推移演变您的数据库架构,同时提供从旧版本数据库迁移到当前架构的方法.

    如果您设置了迁移,则可以致电 dbContext.Database.EnsureMigratedAsync() 将待处理的迁移应用到数据库,并确保数据库与您期望的模型匹配。

    您还可以使用dotnet ef command line utility 创建数据库或应用迁移。

    【讨论】:

    • 谢谢 - 这实际上解释得很好。我实际上已经在使用迁移,我会看看你的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 2012-10-16
    • 2013-03-07
    • 1970-01-01
    • 2018-03-27
    相关资源
    最近更新 更多