在 Linux 上使用 SQLite DB 部署 ASP.Net 核心 API 后'No such table'



UPDATE:我能够在根路径中找到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:UsersmichuDesktopWissenschaftspreis-2021MessdatenControllerMessdatenControllerControllersMeasurementsController.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的路由应该可以正常工作,因为if到达了控制器方法。

现在关于我的文件:

Program.cs保持默认设置。

启动.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();
});
}
}

测量.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);
}
}

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

任何建议都很感激,随时可以问我任何问题-我会尽快回复

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

如果以后要向数据库中添加其他表,则应考虑使用迁移,这样可以随着时间的推移不断发展数据库模式,同时提供从旧版本数据库迁移到当前模式的方法。

如果设置了迁移,可以调用dbContext.Database.EnsureMigratedAsync()将挂起的迁移应用于数据库,并确保数据库与您期望的模型匹配。

您还可以使用dotnet ef命令行实用程序创建数据库或应用迁移。

最新更新