首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用EF和LINQ比较数据库中的信息收集

用EF和LINQ比较数据库中的信息收集
EN

Code Review用户
提问于 2014-04-29 12:14:37
回答 1查看 2.5K关注 0票数 2

我想通知接受者我们这周有新合同。在我发送电子邮件后,有关发送合同的信息存储在MS数据库中。

为了避免有人成为关于合同的同一封电子邮件,我多次执行以下步骤:

  1. 我有新合同作为输入的集合
  2. 我使用实体框架从DB读取有关发送电子邮件的信息
  3. 如果电子邮件已经发送,我将向发送的电子邮件集添加新实例

在此之后,我从输入集合中删除已经在已发送集合中的契约:

代码语言:javascript
复制
public Collection<Contract> GiveContractsThatWereNotSent(Collection<Contract> newThisWeekContracts)
{
   var contractsWereSent = new Collection<Contract>();

   using (var accountingEntities = new AccountingEntities())
   {
      foreach (Contract newContract in newThisWeekContracts)
      {
         bool found = (from sent in accountingEntities .Tbl_SentProtocol
                       where
                          sent.CONTRACT_NO == newContract.ContractNo
                          && sent.CONTRACT_NO_ALT == newContract.ContractNoAlt
                        select sent ).Any();

         if (found)
         {
            contractsWereSent.Add(newContract);
         }
      }
   }    

   foreach (Contract contract in contractsWereSent)
   {
      newThisWeekContracts.Remove(contract);
   }

   return newThisWeekContracts; 
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2014-04-29 15:35:37

有几点:

  • 根据抽象编写代码。Collection是一个特定的实现。
    • 您不需要newThisWeekContracts专门成为一个Collection。我会接受任何IEnumerable<Contract>而不是。
    • 通过返回一个Collection,调用方可以添加或删除它,这可能不是预期的行为。我将返回一个IEnumerable<Contract>,或者,如果添加/删除是可以的,我将返回一个IList<Contract><ICollection<Contract> (即抽象,而不是特定的实现)。

  • 我喜欢描述性的命名,大小写是正确的,但是名字读起来还是有点尴尬。

似乎可以减少查询的数量,但我认为它消耗的资源较少;主要是根据需要将.Where().Any()!.Any()相结合:

代码语言:javascript
复制
public IEnumerable<Contract> GiveContractsThatWereNotSent(IEnumerable<Contract> newContracts)
{
    using (var entities = new AccountingEntities())
    {
        var sentContracts =
                   entities.Tbl_SentProtocol
                           .Where(sent => 
                                  newContracts.Any(contract => 
                                                   sent.CONTRACT_NO == contract.ContractNo
                                                && sent.CONTRACT_NO_ALT == contract.ContractNoAlt))
                           .ToList();

    }

    // ...
}

这给您发送了合同(/ contractsWereSent),但这不是您想要的。现在,您需要返回newContracts (/ newThisWeekContracts)中没有在sentContacts中的契约。

你所拥有的:

代码语言:javascript
复制
foreach (Contract contract in contractsWereSent)
{
    newThisWeekContracts.Remove(contract);
}

包括打电话EqualityComparer.Default在每一个contract,它验证Contract是否实现了IEquatable<T>,否则如果Contract重写了它们,则使用.Equals.GetHashCode的重写,否则使用引用相等.这听起来不太好,因为如果一个契约是“相等”的,当它的ContractNoContractNoAltsendContracts中存在时,当在Tbl_SentProtocol中进行比较时,当我想从newContracts中“删除”项时,我会使用相同的相等比较。

事实上,我不会从newContracts中删除任何东西。为输入保留输入!

这个怎么样?

代码语言:javascript
复制
IEnumerable<Contract> sentContracts;
using (var entities = new AccountingEntities())
{
    sentContracts = // trying to prevent horizontal scrolling...
        entities.Tbl_SentProtocol
                .Where(sent =>  
                       newContracts.Any(contract => 
                                        sent.CONTRACT_NO == contract.ContractNo
                                     && sent.CONTRACT_NO_ALT == contract.ContractNoAlt))
                .ToList();  
}

return newContracts.Where(contract => !sentContracts.Any(sent =>
                                        sent.CONTRACT_NO == contract.ContractNo
                                     && sent.CONTRACT_NO_ALT == contract.ContractNoAlt))
                   .ToList();

还有一件事是,应该命名实体,以便像普通代码一样读取--实体类型SentContract可以映射到表tbl_SentProtocol,属性ContractNumberContractAltNumber可以映射到列CONTRACT_NOCONTRACT_NO_ALT ;)

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/48477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档