Đây không phải là so sánh phân biệt chữ hoa chữ thường trong LINQ với các Đối tượng:
Thingies.First(t => t.Name == "ThingamaBob");
Làm cách nào để có thể so sánh phân biệt chữ hoa chữ thường với LINQ với các Đối tượng?
Đây không phải là so sánh phân biệt chữ hoa chữ thường trong LINQ với các Đối tượng:
Thingies.First(t => t.Name == "ThingamaBob");
Làm cách nào để có thể so sánh phân biệt chữ hoa chữ thường với LINQ với các Đối tượng?
Câu trả lời:
Đó là bởi vì bạn đang sử dụng LINQ To Entities , cuối cùng chuyển đổi các biểu thức Lambda của bạn thành các câu lệnh SQL. Điều đó có nghĩa là phân biệt chữ hoa chữ thường tùy thuộc vào Máy chủ SQL của bạn mà theo mặc định có SQL_Latin1_General_CP1_CI_AS Collation và điều đó KHÔNG phân biệt chữ hoa chữ thường.
Sử dụng ObjectQuery.ToTraceString để xem truy vấn SQL được tạo đã thực sự được gửi đến SQL Server tiết lộ bí ẩn:
string sqlQuery = ((ObjectQuery)context.Thingies
.Where(t => t.Name == "ThingamaBob")).ToTraceString();
Khi bạn tạo truy vấn LINQ to Entities , LINQ to Entities sẽ sử dụng trình phân tích cú pháp LINQ để bắt đầu xử lý truy vấn và chuyển nó thành cây biểu thức LINQ. Sau đó, cây biểu thức LINQ được chuyển đến API dịch vụ đối tượng , nó chuyển đổi cây biểu thức thành cây lệnh. Sau đó, nó được gửi đến nhà cung cấp cửa hàng (ví dụ: SqlClient), nơi chuyển cây lệnh thành văn bản lệnh cơ sở dữ liệu gốc. Truy vấn được thực thi trên kho dữ liệu và kết quả được Vật chất hóa thành các Đối tượng Thực thể bởi Dịch vụ Đối tượng. Không có logic nào được đưa vào giữa để tính đến phân biệt chữ hoa chữ thường. Vì vậy, bất kể trường hợp nào bạn đặt trong vị ngữ của mình, nó sẽ luôn được SQL Server của bạn coi như vậy trừ khi bạn thay đổi SQL Server Collates cho cột đó.
Do đó, giải pháp tốt nhất sẽ là thay đổi đối chiếu của cột Tên trong bảng Thingies thành COLLATE Latin1_General_CS_AS phân biệt chữ hoa chữ thường bằng cách chạy điều này trên Máy chủ SQL của bạn:
ALTER TABLE Thingies
ALTER COLUMN Name VARCHAR(25)
COLLATE Latin1_General_CS_AS
Để biết thêm thông tin về SQL Server Collates , hãy xem phần Tìm kiếm truy vấn SQL phân biệt chữ hoa chữ thường trên SQL SERVER Collate
Giải pháp duy nhất mà bạn có thể áp dụng ở phía máy khách là sử dụng LINQ to Objects để thực hiện một phép so sánh khác có vẻ không được thanh lịch cho lắm:
Thingies.Where(t => t.Name == "ThingamaBob")
.AsEnumerable()
.First(t => t.Name == "ThingamaBob");
Bạn có thể thêm chú thích [Phân biệt chữ hoa chữ thường] cho EF6 + Code-first
Thêm lớp học này
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class CaseSensitiveAttribute : Attribute
{
public CaseSensitiveAttribute()
{
IsEnabled = true;
}
public bool IsEnabled { get; set; }
}
public class CustomSqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator
{
protected override void Generate(AlterColumnOperation alterColumnOperation)
{
base.Generate(alterColumnOperation);
AnnotationValues values;
if (alterColumnOperation.Column.Annotations.TryGetValue("CaseSensitive", out values))
{
if (values.NewValue != null && values.NewValue.ToString() == "True")
{
using (var writer = Writer())
{
//if (System.Diagnostics.Debugger.IsAttached == false) System.Diagnostics.Debugger.Launch();
// https://github.com/mono/entityframework/blob/master/src/EntityFramework.SqlServer/SqlServerMigrationSqlGenerator.cs
var columnSQL = BuildColumnType(alterColumnOperation.Column); //[nvarchar](100)
writer.WriteLine(
"ALTER TABLE {0} ALTER COLUMN {1} {2} COLLATE SQL_Latin1_General_CP1_CS_AS {3}",
alterColumnOperation.Table,
alterColumnOperation.Column.Name,
columnSQL,
alterColumnOperation.Column.IsNullable.HasValue == false || alterColumnOperation.Column.IsNullable.Value == true ? " NULL" : "NOT NULL" //todo not tested for DefaultValue
);
Statement(writer);
}
}
}
}
}
public class CustomApplicationDbConfiguration : DbConfiguration
{
public CustomApplicationDbConfiguration()
{
SetMigrationSqlGenerator(
SqlProviderServices.ProviderInvariantName,
() => new CustomSqlServerMigrationSqlGenerator());
}
}
Sửa đổi DbContext của bạn, thêm
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new AttributeToColumnAnnotationConvention<CaseSensitiveAttribute, bool>(
"CaseSensitive",
(property, attributes) => attributes.Single().IsEnabled));
base.OnModelCreating(modelBuilder);
}
Sau đó làm
Add-Migration CaseSensitive
Cập nhật cơ sở dữ liệu
dựa trên bài viết https://milinaudara.wordpress.com/2015/02/04/case-sensitive-search-using-entity-framework-with-custom-annotation/ với một số sửa lỗi
WHERE
các điều kiện trong SQL Server không phân biệt chữ hoa chữ thường theo mặc định. Làm cho nó phân biệt chữ hoa chữ thường bằng cách thay đổi các đối chiếu mặc định của cột ( SQL_Latin1_General_CP1_CI_AS
) thành SQL_Latin1_General_CP1_CS_AS
.
Cách dễ dàng để làm điều này là với mã. Thêm tệp di chuyển mới và sau đó thêm tệp này vào bên trong Up
phương thức:
public override void Up()
{
Sql("ALTER TABLE Thingies ALTER COLUMN Name VARCHAR(MAX) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL");
}
Nhưng
Bạn có thể tạo chú thích tùy chỉnh được gọi là "Phân biệt chữ hoa chữ thường" bằng cách sử dụng các tính năng EF6 mới và bạn có thể trang trí các thuộc tính của mình như sau:
[CaseSensitive]
public string Name { get; set; }
Bài đăng trên blog này giải thích cách làm điều đó.
Câu trả lời do @Morteza Manavi đưa ra sẽ giải quyết được vấn đề. Tuy nhiên, đối với giải pháp phía máy khách , một cách thanh lịch sẽ là như sau (thêm kiểm tra kỹ).
var firstCheck = Thingies.Where(t => t.Name == "ThingamaBob")
.FirstOrDefault();
var doubleCheck = (firstCheck?.Name == model.Name) ? Thingies : null;
Tôi thích câu trả lời của Morteza và thường muốn sửa ở phía máy chủ. Đối với phía máy khách, tôi thường sử dụng:
Dim bLogin As Boolean = False
Dim oUser As User = (From c In db.Users Where c.Username = UserName AndAlso c.Password = Password Select c).SingleOrDefault()
If oUser IsNot Nothing Then
If oUser.Password = Password Then
bLogin = True
End If
End If
Về cơ bản, trước tiên hãy kiểm tra xem có người dùng với các tiêu chí bắt buộc hay không, sau đó kiểm tra xem mật khẩu có giống nhau không. Hơi dài dòng một chút, nhưng tôi cảm thấy nó dễ đọc hơn khi có thể có một loạt các tiêu chí liên quan.
Cả hai đều không StringComparison.IgnoreCase
làm việc cho tôi. Nhưng điều này đã làm:
context.MyEntities.Where(p => p.Email.ToUpper().Equals(muser.Email.ToUpper()));
How can I achieve case sensitive comparison
Sử dụng string.Equals
Thingies.First(t => string.Equals(t.Name, "ThingamaBob", StringComparison.CurrentCulture);
Ngoài ra, bạn không phải lo lắng về null và chỉ nhận lại thông tin bạn muốn.
Sử dụng StringComparision.CurrentCultureIgnoreCase cho Phân biệt chữ hoa chữ thường.
Thingies.First(t => string.Equals(t.Name, "ThingamaBob", StringComparison.CurrentCultureIgnoreCase);
Không chắc chắn về EF4, nhưng EF5 hỗ trợ điều này:
Thingies
.First(t => t.Name.Equals(
"ThingamaBob",
System.StringComparison.InvariantCultureIgnoreCase)
StringComparison
tạo ra sự khác biệt. Tôi đã thấy đủ người đề xuất loại điều này nên hoạt động để nghĩ rằng vấn đề nằm ở đâu đó trong tệp EDMX (db-first), mặc dù stackoverflow.com/questions/841226/…