gpt4 book ai didi

c# - LINQ to Entities 与文化冲突

转载 作者:太空宇宙 更新时间:2023-11-03 12:21:29 25 4
gpt4 key购买 nike

我有一个 SQL Server 数据库,其中十进制值始终与“.”一起存储。作为小数点分隔符。

我有一个使用用户文化的 ASP.NET MVC 5 应用程序。我正在使用小数分隔符为“,”的“es-ES”文化测试应用程序,当我尝试从具有小数值的表中获取一些值时,它返回了错误的值。

例如

class Model
{
public string Description {get; set;}
public decimal Length {get; set;}
}

数据库中的值

<table>
<th>Description</th>
<th>Length</th>
<tr>
<td>Dog</td>
<td>4.25</td>
</tr>
<tr>
<td>Cat</td>
<td>2.11</td>
</tr>
</table>

当我运行这个查询时

var result = 
from x in DbContext.Model
select x;

我得到 425 而不是 4.25 和 211 而不是 2.11

如何告诉 LINQ 使用不变区域性

这只是展示我需要的片段。在真实场景中我会做这样的事情

var result = 
from x in DbContext.Model
select new
{
Description = x.Description,
Length = x.Length * 2
};

最佳答案

您没有告诉 LINQ 使用不变区域性。 LINQ 只是 IEnumerable<T> 的扩展函数的集合和 IQueryable<T>接口(interface)。

您正在使用 DbContext .这似乎是一个 Entity Framework DbContext , 但即使不是,你的 DbContext应该向您隐藏数字存储在存储中的格式(通常是 SQL 数据库,但不一定是,它可以是 CSV 文件、EXCEL、JSON 等)。

如果你仔细观察你的对象 DbContext.Model , 你会看到这个对象的类实现了 IQueryable<Model> .

这意味着,这个对象可以容纳两个东西:一个Expression。和一个“提供者”。 (好吧,也是一个元素类型,在你的例子中这将是 Model ,在这个讨论中没有意义)

当您使用 DbContext.Model 时作为查询的起点,您实际上正在更改 ExpressionIQueryable<Model>里面.只要您不要求模型序列中的第一个元素 Provider未使用。

Provider向您隐藏模型序列的存储方式。 Provider知道它是关系数据库、CSV 文件还是其他什么。这是Provider的任务翻译 Expression转换为存储理解的格式并从存储中获取数据。

对于 Entity Framework DbContexts,这通常意味着存储是一个 SQL(类)数据库。 Provider知道数据库模型,它知道如何翻译你的 Expression SQL 以及如何与数据库通信。

阅读本文后,您应该明白,DbContext.Model 对象的用户不应该知道存储以何种格式保存小数。这是Provider的任务将小数转换为存储格式。如果这种存储格式将小数存储为西类牙字符串,那么 Provider应该将小数转换为西类牙语字符串。

现在回到你的问题,因为这些知识并不能解决你的问题。

您应该调查为什么西类牙符号会渗透到您的 DbContext.Models

您的数据库存储似乎被告知将长度存储为字符串而不是小数。

如果您的数据库是 SQL,则小数不会保存为字符串,而是保存为具有一定精度的值。

如果数据库将您的长度保存为字符串,那么数据库的设计者会告诉 Entity Framework Model.Length是字符串,不是小数。在这种情况下,您的 Model 的定义类不能正确表示数据库中模型表的内容。 Model.Length不应该是一个小数,而是一个字符串,因此代表你的数据库的结构Model表格

巧妙的解决方案是将数据库中的长度列从字符串更改为精确值(无论您使用的是什么数据库)。如果你不能改变 Model 的结构表你的数据库,你应该改变你的模型类,这样它代表你的模型:

class Model
{
public string Description {get; set;}
public string Length {get; set;}

private static IFormatProvider spanishCulture = CultureInfo.CreateSpecificCulture("es-ES");

[NotMapped]
public decimal LengthInMeters
{
get {return Decimal.Parse(this.Length, spanishCulture);}
set {this.Length = value.ToString(spanishCulture); }
}
}

这也解决了未知长度单位(米?厘米?英寸?)的问题

一个更简洁的解决方案,您可以让 Model类完全代表数据库表,将创建一个 SpanishModel类并创建扩展函数以从 Model 转换至 SpanishModel返回

// model represents exactly database table:
class Model
{
public string Description {get; set;}
public string Length {get; set;}
}

class SpanishModel
{
public string Description {get; set;}
public decimal Length {get; set;}
}

// extension functions of model:
static class ModelExtensions
{
private static IFormatProvider spanishCulture = CultureInfo.CreateSpecificCulture("es-ES");

public static SpanishModel AsSpanishModel(this Model model)
{
return new SpanishModel()
{
Description = model.Description,
Length = Decimal.Parse(model.Length, spanishCulture);
}
}
public static Model AsModel(this SpanishModel model)
{
return new Model()
{
description = model.Description,
Length = model.Length.ToString(spanishCulture),
};
}

public static IEnumerable<SpanishModel> AsSpanishModels(this IEnumerable<Model> models)
{
return models.Select(model => model.AsSpanishModel();
}

public static IEnumerable<SpanishModel> AsModels(this IEnumerable<SpanishModel> models)
{
return models.Select(model => model.AsModel();
}
}

用法:

IEnumerable<SpanishModel> requestedModels = myDbContext.Models
.Where(model => model.Description == ...)
.AsSpanishModels();

参见 Extension Functions Demystified

如果您真的想隐藏 SpanishModels 不是您数据库的一部分的事实,请考虑扩展您的 DbContext 类:

static class MyDbContextExtensions
{
public static IQueryable<SpanishModel> SpanishModel(this MyDbContext dbContext)
{
return dbContext.Models.AsSpanishModels();
}
}

用法:

using (var myDbContext = new MyDbContext(...))
{
IQueryable<SpanishModel> tallSpanishModels = myDbContext.SpanishModels
.Where(model => model.Length > 1.85M);
foreach (SpanishModel tallModel in tallSpanishModels)
{
Console.WriteLine($"{tallModel.Description} has a length of {tallModel.Length}";
}
}

你几乎看不出其他DbSets之间有什么区别你的DbContext和你的 SpanishModel .仔细想想,我认为这是最巧妙的解决方案。

关于c# - LINQ to Entities 与文化冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46962093/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com