Linq to sql LinqToSql.Contains和nvarchar vs varchar参数->;索引转换计划

Linq to sql LinqToSql.Contains和nvarchar vs varchar参数->;索引转换计划,linq-to-sql,orm,Linq To Sql,Orm,我在datacontext中映射了一个单表。以下是感兴趣的列上的属性和属性: [Column(Storage="_CustomerNumber", DbType="VarChar(25)")] public string CustomerNumber { 实际上,该列是一个varchar(25)并有一个索引 我有一些简单的代码: DataClasses1DataContext myDC = new DataClasses1DataContext(); myDC.Log = Console.Ou

我在datacontext中映射了一个单表。以下是感兴趣的列上的属性和属性:

[Column(Storage="_CustomerNumber", DbType="VarChar(25)")]
public string CustomerNumber
{
实际上,该列是一个varchar(25)并有一个索引

我有一些简单的代码:

DataClasses1DataContext myDC = new DataClasses1DataContext();
myDC.Log = Console.Out;

List<string> myList = new List<string>() { "111", "222", "333" };
myDC.Customers
    .Where(c => myList.Contains(c.CustomerNumber))
    .ToList();
请注意,参数是nvarchar

当这个查询访问数据库时,它会生成一个可怕的计划,其中包括将CustomerNumber上的数百万行索引转换为nvarchar,然后再在其中进行搜索


我不允许更改表,但我可以更改查询和dbml。在不进行索引转换的情况下,我能做些什么来获取数据?

以下是我可能的解决方法。我也有兴趣看到其他解决方案:

List<IQueryable<Customer>> myQueries = 
    myList.Select(s => myDC.Customers.Where(c => c.CustomerNumber == s)).ToList();
IQueryable<Customers> myQuery = myQueries.First();
foreach(IQueryable<Customer> someQuery in myQueries.Skip(1))
{
    myQuery = myQuery.Concat(someQuery);
}
myQuery.ToList();

这是我现在每天解决这个问题的方法。这会将参数转换为所需类型,然后运行查询。它生成与最初生成的sql相同的sql,只是参数类型不同

DbCommand myCommand = myDataContext.GetCommand(query);

foreach (DbParameter dbParameter in myCommand.Parameters)
{
  if (dbParameter.DbType == System.Data.DbType.String)
  {
    dbParameter.DbType = System.Data.DbType.AnsiString;
  }
}    

myDataContext.Connection.Open();

System.Data.Common.DbDataReader reader = myCommand.ExecuteReader();
List<RecordType> result = myDataContext.Translate<RecordType>(reader).ToList();

myDataContext.Connection.Close();
DbCommand myCommand=myDataContext.GetCommand(查询);
foreach(myCommand.Parameters中的DbParameter DbParameter)
{
if(dbParameter.DbType==System.Data.DbType.String)
{
dbParameter.DbType=System.Data.DbType.AnsiString;
}
}    
myDataContext.Connection.Open();
System.Data.Common.DbDataReader=myCommand.ExecuteReader();
List result=myDataContext.Translate(reader.ToList();
myDataContext.Connection.Close();

对于我正在处理的项目,我们必须使用
ObjectContext
而不是
DbContext
,因此我无法访问
GetCommand()
DbParameters
。我要做的是将查询转换为字符串,删除查询中的NVARCHAR指示符,然后对
ObjectContext
执行查询。下面是示例的详细实现:

List<string> myList = new List<string>() { "111", "222", "333" };

IQueryable<Customers> badQuery =  myDC.Customers
    .Where(c => myList.Contains(c.CustomerNumber));

string query = ((System.Data.Objects.ObjectQuery)badQuery).ToTraceString();
query = query.Replace(",N'", ",'").Replace("(N'","('");

List<Customers> customers = myDC.ExecuteStoreQuery<Customers>(query).ToList();
List myList=newlist(){“111”、“222”、“333”};
IQueryable badQuery=myDC.Customers
其中(c=>myList.Contains(c.CustomerNumber));
字符串查询=((System.Data.Objects.ObjectQuery)badQuery).ToTraceString();
query=query.Replace(“,N'”,”).Replace(“(N'”,”);
List customers=myDC.ExecuteStoreQuery(query.ToList();

这是可行的,但有一个问题:.Translate方法无法正确地将相关实体加载到t(换句话说,如果您在上下文中添加了.LoadsWith,并且总和与t相关,则此操作将失败)。这是LinqToEntities。我正在使用LinqToSql。据我所知,LinqToEntities没有此查询转换问题。
DbCommand myCommand = myDataContext.GetCommand(query);

foreach (DbParameter dbParameter in myCommand.Parameters)
{
  if (dbParameter.DbType == System.Data.DbType.String)
  {
    dbParameter.DbType = System.Data.DbType.AnsiString;
  }
}    

myDataContext.Connection.Open();

System.Data.Common.DbDataReader reader = myCommand.ExecuteReader();
List<RecordType> result = myDataContext.Translate<RecordType>(reader).ToList();

myDataContext.Connection.Close();
List<string> myList = new List<string>() { "111", "222", "333" };

IQueryable<Customers> badQuery =  myDC.Customers
    .Where(c => myList.Contains(c.CustomerNumber));

string query = ((System.Data.Objects.ObjectQuery)badQuery).ToTraceString();
query = query.Replace(",N'", ",'").Replace("(N'","('");

List<Customers> customers = myDC.ExecuteStoreQuery<Customers>(query).ToList();