【问题标题】:Cannot convert Linq to SQL无法将 Linq 转换为 SQL
【发布时间】:2018-03-12 12:03:34
【问题描述】:

因此,对于我得到的分配,我必须将通过 API 获得的数据转换为对象并将该对象保存在数据库中。由于该对象没有任何唯一的属性,因此我的数据库中有多个主键列。

所以我基本上必须做的是从我的数据库“合并”,所以如果数据已更改为更新,如果数据是新的,请执行插入。出于某种原因,我对此的 linq 查询给出了错误。

我的数据库:

我的代码:

 public void Insert(List<MEDSU1> medsu1s)
        {
            var keys = medsu1s.Select(y => new { SUPP = y.S1SUPP?.Trim() ?? null, COMP = y.S1COMP?.Trim() ??null }).ToList();
            List<MEDSU1> medusFromSql = MediusDataContext.MEDSU1s.Where(y =>
                keys.Any(z => z.SUPP == y.S1SUPP && z.COMP == y.S1COMP)).ToList();


            var toUpdate = from medsu1org in MediusDataContext.MEDSU1s 


                join sqlkeys in medusFromSql
                    on new
                    {
                        aa = medsu1org.S1COMP,
                        bb = medsu1org.S1SUPP
                    }
                    equals
                    new
                    {
                        aa = sqlkeys.S1COMP,
                        bb = sqlkeys.S1SUPP
                    } 
                select new
                {
                    sql = medsu1org,
                    obj = sqlkeys,
                };



            toUpdate.ToList().ForEach(y =>
                        {
                            y.obj.S1COMP= y.sql.S1COMP;
                            y.obj.S1SUPP = y.sql.S1SUPP;
                            y.obj.S1SUNA = y.sql.S1SUNA;
                            y.obj.S1BAAC = y.sql.S1BAAC;
                            y.obj.S1VATN = y.sql.S1VATN;
                            y.obj.S1COUN = y.sql.S1COUN;
                            y.obj.S1PREF = y.sql.S1PREF;
                            y.obj.S1TAXD = y.sql.S1TAXD;
                            y.obj.S1CURR = y.sql.S1CURR;
                            y.obj.S1TYPE = y.sql.S1TYPE;
                            y.obj.S1ACNR = y.sql.S1ACNR;
                            y.obj.S1ACNM = y.sql.S1ACNM;
                            y.obj.S1EINV = y.sql.S1EINV;
                            y.obj.S1DLAY = y.sql.S1DLAY;
                            y.obj.S1TERM = y.sql.S1TERM;
                            y.obj.S1PYEE = y.sql.S1PYEE;
                        });
            var toInsert = medsu1s.Except(toUpdate.Select(y => y.obj)).ToList();
            MediusDataContext.MEDSU1s.InsertAllOnSubmit(toInsert);
            MediusDataContext.SubmitChanges();
}

给我错误的代码部分是:

   var keys = medsu1s.Select(y => new { SUPP = y.S1SUPP?.Trim() ?? null, COMP = y.S1COMP?.Trim() ??null }).ToList();
   List<MEDSU1> medusFromSql = MediusDataContext.MEDSU1s.Where(y =>
                        keys.Any(z => z.SUPP == y.S1SUPP && z.COMP == y.S1COMP)).ToList();

我认为这与我错误地使用 .Any 并将其转换为列表有关,但我不知道如何修复它。有人可以解释一下我做错了什么吗?

我得到错误:“本地序列不能用于查询运算符的 LINQ to SQL 实现中,但包含运算符除外。”

【问题讨论】:

  • 阅读 How to Ask 并将错误以及您对问题的研究包括在内。
  • For some reason one my linq queries for this is giving an error. 关于错误的任何线索?
  • 在帖子中添加了错误。抱歉完全忘记了
  • 尝试以下操作: List medusFromSql = MediusDataContext.MEDSU1s.Where(y => keys.Any(z => z.SUPP == y.S1SUPP && z.COMP == y.S1COMP )).Select(x => new MEDSU1() {在此处添加类属性 s1comp = x.Field("S1Comp") }).ToList();
  • ?? null 有点毫无意义,因为它的字面意思是“如果它为空,则用空替换”

标签: c# linq linq-to-sql


【解决方案1】:

由于您要处理复合键,因此您必须创建一个基本上看起来像

的查询
Select *
From MEDSU1s
Where (S1SUPP == @S1SUPP1 && S1COMP == @S1COMP1)
    OR (S1SUPP == @S1SUPP2 && S1COMP == @S1COMP2)
    OR ....

要使用 Linq 做到这一点,您必须在程序上构建表达式。请注意,我假设列都是字符串,因此根据需要更改它们的类型。我也没有很好的测试方法,但希望这可以让你开始寻找解决方案。

var queryableData = MediusDataContext.MEDSU1s;

var table = Expression.Parameter(typeof(MEDSU1s), "x");

var suppCol = Expression.Property(table, typeof(string), "S1SUPP");
var compCol = Expression.Property(table, typeof(string), "S1COMP");

Expression condition = Expression.Equal(Expression.Constant(1), Expression.Constant(0));
foreach (var x in keys)
{
    var key1 = Expression.Equal(suppCol, Expression.Constant(x.SUPP));
    var key2 = Expression.Equal(compCol, Expression.Constant(x.COMP));
    var both = Expression.AndAlso(key1, key2);
    condition = Expression.OrElse(condition, both);
}

var whereExpression = Expression.Call(
    typeof(Queryable),
    "Where",
    new Type[] { queryableData.ElementType },
    queryableData.Expression,
    Expression.Lambda<Func<MEDSU1s, bool>>(
        condition, 
        new ParameterExpression[] { table }));

var medusFromSql = queryableData.Provider.CreateQuery<MEDSU1s>(whereExpression).ToList();

【讨论】:

  • 您的 SQL 示例只是将相同的条件重复了两次?
  • 这种技术可以使用的参数数量是否有上限?
  • @NetMage 是的,修复了。
  • @mjwills SQL Server 的参数限制为 2,100。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多