好的,我就是这样解决的:
目的是在 Entity Framework Core 中保留地理信息(不使用 DbGeography)
1) 我创建了一个名为 Location 的结构:
public struct Location
{
public double Longitude { get; set; }
public double Latitude { get; set; }
}
2) 将其添加到您的 EF 实体模型中
public class User
{
public Location Location { get; set; }
}
3) 将其隐藏在您的模型构建器中
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().Ignore(x => x.Location);
}
4) 生成迁移(Add-Migration migrationname)
5) 转到您的迁移文件 1231randomnumbers1231_migrationname.cs
并添加以下内容(这样我们创建了另一个名为 Location 的地理类型列),然后更新您的数据库(更新数据库):
migrationBuilder.Sql(@"ALTER TABLE [dbo].[User] ADD [Location] geography NULL");
6)(可选)我创建了一个静态类来更新数据库,如果您在多个表中有一个 Location 列,这将很方便。
public static class GeneralDB
{
public static async Task UpdateLocation(DbContext ctx, string table, Location location, int id)
{
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
string query = String.Format(@"UPDATE [dbo].[{0}] SET Location = geography::STPointFromText('POINT(' + CAST({1} AS VARCHAR(20)) + ' ' + CAST({2} AS VARCHAR(20)) + ')', 4326) WHERE(ID = {3})"
, table.ToLower(), location.Longitude, location.Latitude, id);
await ctx.Database.ExecuteSqlCommandAsync(query);
}
public static async Task<Location> GetLocation(DbContext ctx, string table, int id)
{
Location location = new Location();
using (var command = ctx.Database.GetDbConnection().CreateCommand())
{
string query = String.Format("SELECT Location.Lat AS Latitude, Location.Long AS Longitude FROM [dbo].[{0}] WHERE Id = {1}"
, table, id);
command.CommandText = query;
ctx.Database.OpenConnection();
using (var result = command.ExecuteReader())
{
if (result.HasRows)
{
while (await result.ReadAsync())
{
location.Latitude = result.GetDouble(0);
location.Longitude = result.GetDouble(1);
}
}
}
}
return location;
}
}
这仅适用于 EF Core 2.0
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
对于 EF Core 1.0,您必须找到一种替代方法来将 ',' 替换为 '.'。一个好的老式 .Replace() 方法可以完成这项工作。
location.Longitude.ToString().Replace(',', '.')
7) CRUD 示例:
7.1:阅读
public async Task<User> GetByIdAsync(int id)
{
User user = await ctx.User.AsNoTracking().SingleOrDefaultAsync(x => x.Id == id);
user.Location = await GeneralDB.GetLocation(ctx, "user", id);
return user;
}
7.2:创建
public async Task<User> CreateAsync(User entity)
{
ctx.User.Add(entity);
await ctx.SaveChangesAsync();
await GeneralDB.UpdateLocation(ctx, "user", entity.Location, entity.Id);
return entity;
}
7.3:更新
public async Task<User> UpdateAsync(User entity)
{
ctx.User.Attach(entity);
ctx.Entry<User>(entity).State = EntityState.Modified;
await ctx.SaveChangesAsync();
await GeneralDB.UpdateLocation(ctx, "user", entity.Location, entity.Id);
return entity;
}