删除其他表中没有引用的行

时间:2014-11-21 19:51:51

标签: c# .net sql-server entity-framework linq

我在编写linq查询时遇到问题,因为我是新手。我有两个表RosterSummaryData_Subject_LocalRosterSummaryData_Subject_Local_Bands

Subject_Local包含pkSummarySubjectLocalIDSubject_Local_Bands包含对该表的外键引用(fkSummarySubjectlocalID)。 Subject_Local包含永远不会使用的未使用或孤立的行。我想要做的是删除Subject_Local_Bands中不存在的未使用/孤立的行。

例如,如果我们查看这些示例表:

RosterSummaryData_Subject_Local       RosterSummaryData_Subject_Local_Bands
pkSummarySubjectLocalID               pkSummarySubjectLocalBandID fkSummarySubjectLocalID  Score
1                                     1                           2                        10 
2                                     2                           4                        20
3                                     3                           5                        30
4
5

在这两个表中,您可以看到Subject_Local.pkSummarySubjectLocalIDs中的Subject_Local_Bands 1和3 in永远不会被引用。我想将其从Subject_Local中删除。

这是我目前使用的LINQ代码

var local = customerContext.RosterSummaryData_Subject_Local;
var localBands = customerContext.RosterSummaryData_Subject_Local_Bands;
IEnumerable<RosterSummaryData_Subject_Local> redundantSubjectLocalRows;

redundantSubjectLocalRows = from subjLocal in customerContext.RosterSummaryData_Subject_Local
                            join subjLocalBands in customerContext.RosterSummaryData_Subject_Local_Bands on 
                                 subjLocal.pkSummarySubjectLocalID equals subjLocalBands.fkSummarySubjectLocalID
                            where subjLocalBands.fkSummarySubjectLocalID != subjLocal.pkSummarySubjectLocalID
                            select subjLocal.pkSummarySubjectLocalID;

customerContext.RosterSummaryData_Subject_Local.RemoveRange(redundantSubjectLocalRows);

我想使用RemoveRange所以我需要传递一个IEnumerable我的上下文类RosterSummaryData_Subject_Local,但我不知道如何使用linq查询创建它完成指定的条件。有什么帮助吗?

3 个答案:

答案 0 :(得分:2)

可以说是不优雅的,但这应该是有效的:

HashSet<int> unorphanedIds new HashSet<int>( 
    RosterSummaryData_Subject_Local_Bands
    .Select(b=>b.fkSummarySubjectLocalID));   

var toRemove = customerContext.RosterSummaryData_Subject_Local
    .Where(r=>!unorphanedIds.Contains(r.pkSummarySubjectLocalID));

customerContext.RosterSummaryData_Subject_Local.RemoveRange(toRemove);
customerContext.SaveChanges();

答案 1 :(得分:2)

var local = customerContext.RosterSummaryData_Subject_Local;
var localBands = customerContext.RosterSummaryData_Subject_Local_Bands;

你应该使用except。 A除外,B返回A中但不包含在B中的所有值。 我们选择除local.pkSummarySubjectLocalID之外的所有localBands.fkSummarySubjectLocalID,结果为pkSummarySubjectLocalID但不在local中的所有localBands

var orphanedIds = local.Select(x => x.pkSummarySubjectLocalID)
                      .Except(localBands.Select(x => x.fkSummarySubjectLocalID));

然后我们将此结果(orphanedIds)加入local并获取所有孤立的local

var orphaned = from l in local
      join id in orphanedIds on l.pkSummarySubjectLocalID equals id
      select l;

现在是时候删除所有孤儿local

local.RemoveRange(orphaned);
customerContext.SaveChanges();

答案 2 :(得分:1)

瑞恩

您可以使用LINQ查询中的以下语句创建RosterSummaryData_Subject_Local类。

public void TestMethod()
{
    DataSet lDataSet = new DataSet();

    var lOutput = (from lRosterSummaryBand in lDataSet.Tables[0].AsEnumerable()
                   select new RosterSummaryData_Subject_Local 
                   {
                       //Assign the field value for each row to the model property specified.
                       //Make sure to use the correct data types specified from the data base.
                       pkSummarySubjectLocalID = lRosterSummaryBand.Field<System.Int64>("pkSummarySubjectLocalID") // Column name from DataTable / DataSet
                   }).ToList();//Make sure to set the output as an enumeration
}

数据存储在var集合中,但您可以使用()将它们转换为对象。

值得注意的是,当LINQ为这个var集合分配值时,它通过引用而不是值来实现。对var进行的任何更改都将改变DataTable / DataSet。

或者您也可以执行以下操作。这将保留连接两个表,将它们分配给模型,并只选择子表为空/无值的行。

var lRowsMarketForDeletion = (from lSubjectLocal in lDataSet.Tables[0].AsEnumerable()
                                      join lSubjectLocalbands in lDataSet.Tables[1].AsEnumerable() on lSubjectLocal.Field<System.Int64>("pkSummarySubjectLocalID") equals lSubjectLocalbands.Field<System.Int64>("pkSummarySubjectLocalID") into lJoinedGroup
                                      from lJoinedRow in lJoinedGroup.DefaultIfEmpty(new RosterSummaryData_Subject_Local { pkSummarySubjectLocalID = 0 })
                                      where lJoinedRow.pkSummarySubjectLocalID == 0
                                      select new RosterSummaryData_Subject_Local
                                      {
                                          pkSummarySubjectLocalID = lRosterSummaryBand.Field<System.Int64>("pkSummarySubjectLocalID")
                                      }).ToList();

customerContext.RosterSummaryData_Subject_Local.RemoveRange(lRowsMarketForDeletion);

参考文献:

http://msdn.microsoft.com/en-us/library/bb311040.aspx加入表格。

linq to sql using select new inside class file选择每行的新对象。

http://www.dotnet-tricks.com/Tutorial/linq/UXPF181012-SQL-Joins-with-C左派如何工作。

如果您还有其他需要,请告诉我。