Eli*_*Eli 3 c# entity-framework asp.net-web-api entity-framework-core
我正在尝试实体框架核心,偶然发现了一个我从未见过的错误,无法弄清楚如何修复它.我正在使用.net Core Web API 2.0和EntityFramework Core 2.00-preview2-final
这是一个触发错误的简单示例.
(概念:从数据库中获取用户的简单端点)
错误:System.PlatformNotSupportedException:此平台不支持类型Udt.
有什么建议?
问题是我在我的数据库中使用地理,但我在模型中将它用作字符串,因为实体框架核心还不支持空间数据......
如何在不摆脱地理位置的情况下保持这种蛋糕的美味,这是一个重要特征吗?
编辑:请参阅我当前解决方案的答案
好的,我是如何解决它的:
目的是将地理位置保留在Entity Framework Core中(不使用DbGeography)
1)我创建了一个名为Location的结构:
public struct Location
{
public double Longitude { get; set; }
public double Latitude { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
2)将其添加到您的EF实体模型
public class User
{
public Location Location { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
3)在模型构建器中隐藏它
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().Ignore(x => x.Location);
}
Run Code Online (Sandbox Code Playgroud)
4)生成迁移(添加迁移迁移名称)
5)转到您的迁移文件1231randomnumbers1231_migrationname.cs并添加以下内容(这样我们创建另一个名为Location的地理类型列),然后更新您的数据库(update-database):
migrationBuilder.Sql(@"ALTER TABLE [dbo].[User] ADD [Location] geography NULL");
Run Code Online (Sandbox Code Playgroud)
6)(可选)我创建了一个静态类来更新数据库,如果在mulple表中有一个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;
}
}
Run Code Online (Sandbox Code Playgroud)
这仅适用于EF Core 2.0
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
Run Code Online (Sandbox Code Playgroud)
对于EF Core 1.0,您必须找到用'.'替换','的替代方法.一个很好的旧时尚.Replace()方法可以完成这项工作.
location.Longitude.ToString().Replace(',', '.')
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3934 次 |
最近记录: |