I wrote this simple query:
var connectionString = String.Format("Url={0}; Username={1}; Password={2}; Domain={3}", url, username, password, domain);
var myConnection = CrmConnection.Parse(connectionString);
CrmOrganizationServiceContext _service = new CrmOrganizationServiceContext(myConnection);
var whoAmI = _service.Execute(new WhoAmIRequest());
var query = new QueryExpression
{
EntityName = "phonecall",
ColumnSet = new ColumnSet(true)
};
query.PageInfo = new PagingInfo
{
Count = 20,
PageNumber = 1,
PagingCookie = null
};
query.Orders.Add(new OrderExpression
{
AttributeName = "actualstart",
OrderType = OrderType.Descending
});
query.Criteria = new FilterExpression() { FilterOperator = LogicalOperator.And };
query.Criteria.AddCondition("call_caller", ConditionOperator.In, lines);
var entities = _service.RetrieveMultiple(query).Entities;
I have a program which runs this query every minute. On the first execution the correct results are displayed but for subsequent queries the results never change as I update records in CRM.
If I restart my program the results refresh correctly again on the first load.
Why are the results not updating as records are modified in CRM?
It is the CrmOrganizationServiceContext that is doing the caching - I found the following worked a treat and the results of my RetrieveMultiple are no longer cached :)
Context = new CrmOrganizationServiceContext(CrmConnection.Parse(connectionString));
Context.TryAccessCache(cache => cache.Mode = OrganizationServiceCacheMode.Disabled);
RetrieveMultiple always brings back fresh results so there must be some other aspect of your program which is causing stale data to be displayed.
Related
my linq method system from EF6 is returning $ref when I monitor results in fiddler. If I watch the local window in my webapi everything is populated correctly, but not in the actual results that are returned. It only affects the nested entries. anyone know what I am doing wrong? (I created models from database in EF6)
var student = dbEF.Accounts
.Where(x => x.AccountNumber == acctNum)
.Select(x => new DTOCrmDetails()
{
AccountNumber = x.AccountNumber,
CommissionId = x.CommissionId,
Commission = x.Commission,
ManagerID = x.ManagerID,
ManagerName = x.Manager.ManagerName,
Manager = x.Manager,
Employees = x.Manager.Employees,
WireInstructionsUSD = x.Manager.WireInstructionsUSDs
//Mapping_ManagersExecutingBrokers = x.Manager.Mapping_ManagersExecutingBrokers
}).FirstOrDefault();
return student;
these are my settings.
var json = config.Formatters.JsonFormatter; json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects; config.Formatters.Remove(config.Formatters.XmlFormatter); config.Formatters.JsonFormatter.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented; config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
You need to disable your lazy loading in the entity framework dbcontext.
something like this way:
dbEF.Configuration.LazyLoadingEnabled = false;
How can I find (preferably using CRM Linq) parent entities that have 0 children. For example how can I find all accounts that have 0 contacts.
If you are going to use the query expression route, which I would recommend then the following code will be useful
var entityAlias = "con";
var query = new QueryExpression
{
EntityName = "account",
ColumnSet = new ColumnSet(true),
Criteria =
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression(entityAlias, "contactid",ConditionOperator.Null)
}
}
LinkEntities =
{
new LinkEntity
{
EntityAlias = entityAlias,
LinkFromEntityName = "account",
LinkFromAttributeName = "accountid",
LinkToEntityName = "contact",
LinkToAttributeName = "parentcustomerid",
Columns = new ColumnSet("parentcustomerid", "contactid"),
JoinOperator = JoinOperator.LeftOuter,
}
},
};
var response = service.RetrieveMultiple(query);
var accounts = response.Entities;
In this code I have not limited the columns, this will reduce performance and you should only return the columns needed.
If there is the case for more than 5000 records are going to be returned then you will need to use paging and loop the query to find all the entities,
This can be found here:
https://msdn.microsoft.com/en-us/library/gg327917.aspx
However if you are certain you want to use LINQ then you can use the following code:
public static IEnumerable<Account> FindAccountsWithNoContacts()
{
var contactRelationship = new Relationship("contact_customer_accounts");
foreach(var account in XrmContext.AccountSet)
{
XrmContext.LoadProperty(contactRelationship);
if(!account.RelatedEntities.ContainsKey(contactRelationship)
yield return account;
}
}
My problem with the LINQ code is that all the enities, both the account and contact entities, will be loaded into memory. With large entity sets this can cause OutOfMemoryException, whereas the query expression route will pass the query to the Dynamics server to execute; which should make the execution of the code faster.
The thing you are looking for is left outer join. Which is unfortunately not possible in CRM using LINQ. However you can do it using query expression or FetchXML.
Here is a link that can help you:
https://community.dynamics.com/crm/b/gonzaloruiz/archive/2014/02/23/all-about-outer-join-queries-in-crm-2011-and-crm-2013
Trying to update a list of Incident records. The first one in the foreach updates, the next one throws an exception stating "the context is not currently tracking the incident entity". Is this the correct way to code this?
var openCases = (from o in xrmContext.IncidentSet
where o.StateCode == 0
select o).Take(5).ToList();
foreach (var c in openCases)
{
var numDays = ((TimeSpan) (DateTime.Now - c.CreatedOn)).Days;
Console.WriteLine("case age: {0}, case number:{1}", numDays, c.TicketNumber);
c.new_caseage = numDays;
xrmContext.UpdateObject(c);
xrmContext.SaveChanges();
}
When you call SaveChanges() it, in addition to saving any modified entity records, detaches all entity records being tracked in the context. Therefore, the second time you call SaveChanges() the entity record is not being tracked and you receive the error.
You should move the xrmContext.SaveChanges(); line to be after the foreach loop.
var openCases = (from o in xrmContext.IncidentSet
where o.StateCode == 0
select o).Take(5).ToList();
foreach (var c in openCases)
{
var numDays = ((TimeSpan) (DateTime.Now - c.CreatedOn)).Days;
Console.WriteLine("case age: {0}, case number:{1}", numDays, c.TicketNumber);
c.new_caseage = numDays;
xrmContext.UpdateObject(c);
}
xrmContext.SaveChanges();
All entities are detached by the OrganizationServiceContext after calling the SaveChanges method. To continue using the data context against previously retrieved entities, the entities need to be reattached.
However, the preference is to apply all modifications under a single call to SaveChanges, and then dispose the context, to avoid the need to reattach.
http://msdn.microsoft.com/en-us/library/gg695783.aspx
http://msdn.microsoft.com/en-us/library/gg334504.aspx#track_related
A better way to do what your try to do is using the message ExecuteMultipleRequest, with it can configure how many record to process for every iteration (internal iteration)
var openCases = (from o in xrmContext.IncidentSet
where o.StateCode == 0
select o).Take(5).ToList();
var requestWithResults = new ExecuteMultipleRequest()
{
// Assign settings that define execution behavior: continue on error, return responses.
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = false,
ReturnResponses = true
},
// Create an empty organization request collection.
Requests = new OrganizationRequestCollection()
};
foreach (var c in openCases)
{
var numDays = ((TimeSpan) (DateTime.Now - c.CreatedOn)).Days;
c.new_caseage = numDays;
CreateRequest createRequest = new CreateRequest { Target = c };
requestWithResults.Requests.Add(createRequest);
}
ExecuteMultipleResponse responseWithResults =
(ExecuteMultipleResponse)_serviceProxy.Execute(requestWithResults);
Hope it helps
I have an entity called Invoice and an entity called InvoiceItem.
There is a one to many relationship called new_invoice_invoiceitem.
There is a LookupAttribute in InvoiceItem called new_parent_invoice_invoiceitem.
I am trying to retrieve the InvoiceItems that are related to the Invoice with a particular ID using the following code:
QueryExpression query = new QueryExpression();
query.EntityName = "new_invoiceitem";
query.ColumnSet = new AllColumns();
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "new_parent_invoice_invoiceitem";
condition.Values = new object [] { new Guid("fe1009cc-e034-49d5-bc59-ab4c3091a6f9") };
condition.Operator = ConditionOperator.Equal;
FilterExpression filter = new FilterExpression();
filter.AddCondition(condition);
query.Criteria = filter;
RetrieveMultipleRequest request = new RetrieveMultipleRequest();
request.Query = query;
RetrieveMultipleResponse response = (RetrieveMultipleResponse)crmService.Execute(request);
BusinessEntityCollection bec = response.BusinessEntityCollection;
The code runs without errors but the BusinessEntityCollection is always empty even though there are records in Dynamics.
Any idea what I'm doing wrong?
Thanks,
David
Try setting request.ReturnDynamicEntities = true
private Boolean Saveuser(bool isNew)
{
tb_User user = new tb_User();
user.User_Name = txtUserName.Text.Trim();
user.User_LoginName = txtLoginName.Text;
user.User_Password = txtPassord.Text;
user.User_ModifiedBy = clsGlobalVariable.strusername;
user.User_Modified = DateTime.Now;
user.User_IsDeleted = false;
user.User_IsUpdated = true;
user.User_UserGroup = "";
user.User_UserType = "";
user.User_WarehouseCode = "";
user.SetIsNew(isNew);
user.Save();
}
when I try to insert new user using above coding, it is worik, but try to update existing user by passing isNew (false). It is not working, when I trace inside activerecord.cs, the dirty column count is always 0 for both new and update. How can I update the existing record?
Please answer for me?
Thanks.
You should
Get the record
Update record
Save
User u = User.FetchByID(2345);
u.User_Name = "blablabla";
//other User object modifications...
u.Save();