使用LINQ从Microsoft CRM检索数据时出现奇怪的行为

本文关键字:LINQ Microsoft CRM 数据 检索 使用 | 更新日期: 2023-09-27 18:12:20

我在使用LINQ访问Contact实体时遇到了这个问题。

我有下面的两个函数。

如果我运行第一个函数,然后调用第二个函数,我似乎在第二个查询中丢失了很多字段。比如名字和姓氏都没有出现。它们只是显示为空值。如果我单独运行第二个函数,我就得到了正确的数据。在两次运行中正确显示的字段只有Id、ContactId和new_username。

如果我单独运行第二个函数,我得到了正确的数据。

你知道我做错了什么吗?

Thanks a lot

下面是两个函数

    public List<String> GetContactsUsernameOnly()
    {
        IQueryable<String> _records = from _contactSet in _flinsafeContext.ContactSet
                                       where
                                           _contactSet.new_FAN == "username"
                                       orderby _contactSet.new_username
                                       select _contactSet.new_username;
        return _records.ToList();
    }
    public List<Contact> GetContacts()
    {
        IQueryable<Contact> _records = from _contactSet in _flinsafeContext.ContactSet
                                       where
                                           _contactSet.new_FAN == "my-username-here"
                                       orderby _contactSet.new_username
                                       select _contactSet;
        return _records.ToList();
    }

使用LINQ从Microsoft CRM检索数据时出现奇怪的行为

这是因为当您调用这两个方法(在您的示例中为_flinsafeContext)时,您正在重用相同的CRM上下文

上下文所做的是缓存记录,所以第一个方法是返回您的联系人,但只带回new_username字段。

第二个方法想要返回整个记录,但是当它在第一个方法之后被调用时,记录已经存在于上下文中,所以它只返回那个,尽管只填充了一个字段。惰性加载尚未填充的字段是不够聪明的。如果这个方法被先调用,它在上下文中不存在,因此将返回整个记录。

有两种方法可以绕过这个:

1)不要重用CRMContexts。而是在每个方法中基于一个单例IOrganizationService创建一个新的。

2)在您的上下文中有一个ClearChanges()方法,这意味着下次您执行查询时,它将返回CRM并获得您所选择的字段。这也将清除任何未保存的创建/更新/删除等,所以你必须小心上下文处于什么状态。

顺便说一句,创建一个新的CRM上下文不是一个密集的操作,所以传递上下文并重用它们通常是不值得的。它正在创建底层的organizationservice,这是最慢的。

这种行为是非常痛苦的,因为它是非常低效和缓慢的返回整个记录,所以你想只选择你想要的字段为每个查询。

这里是你如何返回你想要的字段:

IEnumerable<ptl_billpayerapportionment> bpas = context.ptl_billpayerapportionmentSet
.Where(bm => bm.ptl_bill.Id == billId)
.Select(bm => new ptl_billpayerapportionment()
{
    Id = bm.Id,
    ptl_contact = bm.ptl_contact
})

这将确保对上下文执行更小的sql语句,因为Id和ptl_contact是唯一返回的两个字段。但是正如Ben上面所说的,在相同的上下文中对同一实体的进一步检索将为初始选择中未包含的字段返回null(根据OP的问题)。

额外的好处是,使用IEnumerable并创建一个新的轻量级实体可以让你访问常用的LINQ方法,例如。any(),。sum()等。显然,CRM SDK不喜欢对var数据集使用它们。