Updating an Entity Without Saving the Data back to the Database - linq

I have created a new query like the following
var pressData = from press in dataContext.Releases
select new
{
Heading = press.Heading,
Description = press.Desc,
DatePublished = press.PublishDate.ToString(),
Body = press.BodyContent,
ID=press.ReleaseID,
CreatedBy=press.CreatedBy
};
Later in the code I want to update the entity from a session variable, but not save any data back to the database. Here is the code I am trying to accomplish this with....
var edit = pressData.Where(a => a.Heading == sectionPreview.HeadingContent && a.ID == sectionPreview.tionID).FirstOrDefault();
if (edit != null)
{
//WONT LET ME UPDATE THE Body VALUE
edit.Body = sectionPreview.SectionContent;
}
The code aboves purpose is to look at pressData and replace the body content with the new body from a session variable(not shown here), but NOT save it to the db. I want pressData to be filtered and updated only in the entity. So when I bind it to the control in this case it binds the data stored in my session.
this.rptSections.DataSource = pressData;
this.rptSections.DataBind();
I am getting a complier error stating
Property or indexer 'AnonymousType#1.Body' cannot be assigned to -- it is read only.
I checked the entity model and nothing is read only not any fields not anything. I must be missing something?

Anonymous Types encapsulate a read only property collection - for more information, read here. The compiler rewrites anonymous types as a constructor injections, ie:
select new
{
Heading = press.Heading,
Description = press.Desc,
DatePublished = press.PublishDate.ToString(),
Body = press.BodyContent,
ID=press.ReleaseID,
CreatedBy=press.CreatedBy
};
Is really rewritten as:
new Anonymous`1(press.Heading, press.Desc, press.PublishDate.ToString(), press.BodyContent, press.ReleaseID, press.CreatedBy)
And the properties are read only (public get, private / protected set, to use an easy comparison). If you want to solve your issue, instead of taking the data and making an anonymous object, create a real type and set properties on it.

Related

Update picklist value to null with Sdk.Sync.Update does nothing

Is it possible to update a record's attribute of picklist type with null by using Sdk.Sync.Update? It's not working for me.
Here's what I do:
var detailsObj = updatedDetailsObj; // I get updatedDetailsObj from previous logic, not shown here
var operation = new Sdk.Entity("kcl_operation");
operation.setId(operationId, false); // I have operationId from previous logic, not shown here
operation.addAttribute(new Sdk.String("op_updatedAccount", detailsObj.UpdatedAccount)); // works, get updated
operation.addAttribute(new Sdk.OptionSet("op_updatedExplanation", null)); // doesn't get updated
Sdk.Sync.update(operation);
After the completion of Sdk.Sync.update, the string field get updated, but the picklist field is left with its previous value, instead of null.
I also took a look inside the XML being sent inside Sdk.Sync.update, and indeed, it lacks the pair of "op_updatedExplanation" and null.
How can make it work?
Added:
I'm not doing it inside a form but inside a grid page, so that the user checks several records and I need to make the update on all of them.
standard CRM SDK code (assuming entity name and field name):
Entity operation = new Entity("kcl_operation");
operation.Id = operationId;
operation["op_updatedexplanation"] = null;
service.Update(operation);
where service is an IOrganizationService instance
Please use this snippet to set value as null.
Xrm.Page.getAttribute("op_updatedexplanation").setValue(null);
This will just set the value in the form. You may have to save the form to see the value getting stored in database.
Xrm.Page.data.entity.save();
If the control is disabled - you have to set the submitmode attribute also.
Xrm.Page.getAttribute("op_updatedexplanation").setSubmitMode("always");

Wakanda Datastore - Find and Replace?

I've got a lot of values in a legacy Wakanda datastore which I need to update to some new values. Is there a curl-like command in the wakanda data browser page that can be used to do a mass find-and-replace in a table?
If your dataclass is called MyDataClass and the attribute you want to update is myAttribute you can use the following server-side script :
var newValue = "new value";
ds.MyDataClass.all().forEach(function(entity){
entity.myAttribute = newValue;
entity.save();
});
You can also use a transaction if you want to commit or rollback the whole operation
I don't think there is a way to do a mass of find/replace in the dataBrowser,
But I suggest you to use a query in the server side that search the records with the value you need to replace, and then a loop on this collection to set the new values
As mentioned in other answers, you are likely best to loop over a collection. There is no concept of a mass replace in Wakanda like you see in many other databases.
var myCollection = ds.DataClassName.query("attributeName == :1", "valueToFind");
myCollection.forEach(function(e){
e.attributeName = "newValue";
e.save();
});
So a fake "person" data type might look like this:
var blankFirsts = ds.Person.query("firstname == :1", "");
blankFirsts.forEach(function(person){
person.firstname = "no name";
person.save();
});

Cannot specify child attributes in the columnset for Retrieve

In attempting to merge contacts in Microsoft CRM, I am using the following code -
//c1ID and c2ID are GUIDs of duplicated contacts.
EntityReference target = new EntityReference();
target.LogicalName = Contact.EntityLogicalName;
target.Id = c2ID;
MergeRequest merge = new MergeRequest();
// SubordinateId is the GUID of the account merging.
merge.SubordinateId = c1ID;
merge.Target = target;
merge.PerformParentingChecks = true;
Contact updater = new Contact();
Contact updater2 = new Contact();
updater = (Contact)xrmSvc.ContactSet.Where(c => c.ContactId.Equals(c1ID)).First();
updater2 = (Contact)xrmSvc.ContactSet.Where(c => c.ContactId.Equals(c2ID)).First();
MergeResponse mergedR = (MergeResponse)xrmSvc.Execute(merge);
When I try my Execute call here,I get this error -
Cannot specify child attributes in the columnset for Retrieve. Attribute: owneridname.
Am I not setting something correctly?
Having updatecontent does not change the issue. In fact, I get the error on lookups entered into the updatecontent. I find you have to build new entityreferences:
if (match.Contains("new_mostrecentcampaign"))
master["new_mostrecentcampaign"] =
new EntityReference(match.GetAttributeValue<EntityReference>("new_mostrecentcampaign").LogicalName
, match.GetAttributeValue<EntityReference>("new_mostrecentcampaign").Id);
...
Merge.UpdateContent = master
...
I realize this is a pretty old question, but for those of you who have run into the same issue in 2021 and beyond, here's the reason this error happens.
TL;DR: Ensure the EntityReference values for the attributes does not specify the Name property.
Explanation:
Everything that gets added to the Entity set to UpdateContent will be applied to the Target contact. When programmatically executing a MergeRequest within a plugin/workflow, the attributes of the UpdateContent get applied (as desired).
Where this breaks down is for EntityReference value types (lookups). The internal Microsoft code that performs this operation tries to interpret all properties of the EntityReference object, including Name.
So when the existing values from the SubordinateId contact are pulled using IOrganizationService.Retrieve (to dynamically get the latest version), the Name property is automatically set for those lookup attributes (the child record). This operation is not valid, even though it's not the user code that's directly executing it.
This brings us full circle to explain the original error:
Cannot specify child attributes in the columnset for Retrieve
I wish I had some documentation for this, but although the official documentation notes that the UpdateContent is optional, experience proves that it is in fact necessary. In the MergeRequests I've tested, I always include that property in the request, and there's a post in the MSDN forums for Dynamics 3.0 that suggests the same.
In fact, when I try to merge two contacts in my org without UpdateContent assigned, I actually get a FaultException saying the following:
Required field 'UpdateContent' is missing
Even though the documentation says it's optional!
So I'd suggest populating the UpdateContent property with something as in the below and see if that works:
var merge = new MergeRequest
{
// SubordinateId is the GUID of the account merging.
SubordinateId = c1ID,
Target = target,
PerformParentingChecks = true,
UpdateContent = new Contact()
};

How to find a template in Alfresco with OpenCMIS from Spring application?

I am working in a Spring 3.1 application and I need to find a String template document located in Alfresco's repository. I can already create a file in alfresco with OpenCMIS, but I couldn't figure out how to find a template, so if anyone knows how to do it or point me an example, please let me know, thanks in advance!
There are a number of options you can use. First of all, you need to have a criteria that uniquely identifies your document. Here below I'll show some, hopefully your case falls in one of them or they will inspire you towards a proper solution. The following uses pseudo code, please have a look to the OpenCMIS dev guide for working with the Java client API.
BY ID
Once you create a Document via CMIS, you get the unique ID of it that you can store in your application for later retrieval.
Map<String, Object> templateProperties = createDocumentProperties();
Folder folder = getTemplatesFolder();
ObjectId templateId = createTemplateIn(folder);
storeTemplateId(templateId.getId(), templateProperties); // persist the ID
...
// later on
...
String id = getTemplateId(); // retrieve the ID
Session session = openCMISSession();
Document template = (Document)session.getObject(id);
BY PATH
Similar to the previous example, you will have to take note of where you stored the document instead of its ID, or having a way to construct the path by hand.
String path = getTemplatePath(); // either recover it from DB or construct a path
Document template = (Document)session.getObjectByPath(path);
BY PROPERTY VALUE
Let's say you can use a specific metadata field on a template Document that allows you to easily retrieve it afterwards (e.g. you created some specific Alfresco metadata model for your use case).
String meta = TemplateProperties.TEMPLATE_ID; // e.g. my:templateId
String type = TemplateProperties.TEMPLATE_TYPE; // e.g. my:template
String templateMeta = "TEMPLATE1";
Map<String, Object> templateProperties = createDocumentProperties();
templateProperties.put(meta, templateMeta);
templateProperties.put(PropertyIds.OBJECT_TYPE_ID, type);
createTemplate(templateProperties);
...
// later on
...
String type = TemplateProperties.TEMPLATE_TYPE; // e.g. my:template
String meta = TemplateProperties.TEMPLATE_ID;
String tplId = "TEMPLATE1";
String query = String.format("SELECT * FROM % WHERE % = '%'", type, meta, tplId);
ItemIterable<QueryResult> i = session.query(query, false);
QueryResult qr = i.iterator().next(); // let's assume we have one single match
String templateId = qr.getPropertyByQueryName("cmis:objectId").getFirstValue()
Document template = (Document)session.getObject(templateId);
BY QUERY
The previous approach is not really tied to search by property name, and can be easily extended to use any kind of query that identifies your templates. Have a look at the Alfresco page on its CMIS query language implementation details to learn more ways of querying the repository.

How do I return strong type object in Linq?

I have a stored proc that returns a list of users (rows in User table).
var admins = db.aspnet_UsersInRoles_GetUsersInRoles('/', "Admin");
LINQ generated aspnet_User classes for me, so can I somehow map the result to a List of aspnet_User type? Something like:
List<aspnet_User> admins = db.aspnet_UsersInRoles_GetUsersInRoles('/', "Admin");
Here is a capture of what is returned.
It's entirely possible that you just need:
List<aspnet_User> admins = db.aspnet_UsersInRoles_GetUsersInRoles('/', "Admin")
.ToList();
But it's hard to know without seeing what type the method call returns.
Perhaps this should be a comment but it is way too long...
Well, you do not really want the internal class <aspnet_User> you should want a MembershipUser.
So how about not using the stored procedure that comes with the membership provider but really use the Membership provider itsself.
There is a beautiful class: Roles in System.Web.Security
And it gives you this:
public static string[] GetUsersInRole(string roleName)
From here, a foreach to get the MembershipUser(s) in a list is not that complicated.
By default a stored procedure will return a type that it determines based on the output columns with Result tacked on to the end. It doesn't associate it with types you have already determined. To change this, you can either change the Return Type in the property window to the type you have already defined in your model, or when dragging the stored proc into your model, drop it directly on the type that you want the stored proc to be mapped into.
You don't get the opportunity to change the column mappings for stored procs however, so make sure the shape that the stored proc generates is the same as your target object structures.
It's an old post and I was working on it today and I get the same issue,
I think you are requesting asp membership ?
You can not convert this stored procedure to aspnet_User because it returns aspnet_UsersInRoles_GetUsersInRolesResult type.
but from this aspnet_UsersInRoles_GetUsersInRolesResult you can get userName, then request the aspnet_User table:
String app = "your application name";
String role = "your role name";
ArrayList userInRoleList = new ArrayList();
//Get the role ID
ASPNETDBDataContext aspDB = new ASPNETDBDataContext();
var userInRole = aspDB.aspnet_UsersInRoles_GetUsersInRoles(app, role);
foreach (aspnet_UsersInRoles_GetUsersInRolesResult users in userInRole)
{
userInRoleList.Add(users.UserName);
}

Resources