Azure Cosmos Db document - want to use replacedocumentasync with a removed property in the document - azure

// I am using code like below
Document doc = client.CreateDocumentQuery<Document>(collectionLink)
.Where(r => r.Id == "doc id")
.AsEnumerable()
.SingleOrDefault();
doc.SetPropertyValue("MyProperty1", "updated value");
Document updated = await client.ReplaceDocumentAsync(doc);
Want to remove "MyProperty2" from the document. How to do this?

It seems that you'd like to update MyProperty1 property and remove MyProperty2 property from your document, the following sample code is for your reference.
private async Task updateDoc()
{
string EndpointUri = "xxxxx";
string PrimaryKey = "xxxxx";
DocumentClient client;
client = new DocumentClient(new Uri(EndpointUri), PrimaryKey);
Document doc = client.CreateDocumentQuery<Document>(UriFactory.CreateDocumentCollectionUri("testdb", "testcoll"))
.Where(r => r.Id == "doc5")
.AsEnumerable()
.SingleOrDefault();
//dynamically cast doc back to your MyPoco
MyPoco poco = (dynamic)doc;
//Update MyProperty1 of the poco object
poco.MyProperty1 = "updated value";
//replace document
Document updateddoc = await client.ReplaceDocumentAsync(doc.SelfLink, poco);
Console.WriteLine(updateddoc);
}
public class MyPoco
{
public string id { get; set; }
public string MyProperty1 { get; set; }
}
My document:
Updated:
Edit:
this would remove "MyProperty3" and "MyProperty4" as well.
As you mentioned, setting property with null would be also a approach.
Document doc = client.CreateDocumentQuery<Document>(UriFactory.CreateDocumentCollectionUri("testdb", "testcoll"))
.Where(r => r.Id == "doc5")
.AsEnumerable()
.SingleOrDefault();
doc.SetPropertyValue("MyProperty2", null);
//replace document
Document updateddoc = await client.ReplaceDocumentAsync(doc.SelfLink, doc);

Thanks for replying. You got it what I was asking for.
I did not want to use MyPoco as using Microsoft.Azure.Document is the most flexible. Also, using this approach would also remove any MyProperty3 if it exists with MyPoco.
Using Document class only, following worked:
eachDoc.SetPropertyValue("MyProperty2", null);

Related

In Edit method, updating data create new data instead mvc5

This is my Controllers Edit Method in Httpost
[HttpPost]
public ActionResult Edit(Employee employee)
{
if (!ModelState.IsValid)
{
var department = db.Departments.ToList();
var viewModel = new EmployeeViewModel
{
Departments = department,
Employees = db.Employees.ToList()
};
return View("Index", viewModel);
}
db.Entry(employee).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
this method creates new data instead of updating data.
The problem is you're trying to update Employee instance directly based from action parameter without seeking any matching record first, hence EF "unaware" if the entity should be modified and treat its state as EntityState.Added in this line:
db.Entry(employee).State = EntityState.Modified;
What you should do is using SingleOrDefault() or FirstOrDefault() to fetch matching record based from Id property, update all required properties then attach Employee instance into Employees entity and set its state as EntityState.Modified:
[HttpPost]
public ActionResult Edit(Employee employee)
{
if (!ModelState.IsValid)
{
var department = db.Departments.ToList();
var viewModel = new EmployeeViewModel
{
Departments = department,
Employees = db.Employees.ToList()
};
return View("Index", viewModel);
}
// find employee with matching ID first
var selectedEmployee = db.Employees.SingleOrDefault(x => x.Id == employee.Id);
// update all properties
selectedEmployee.Name = employee.Name;
// other properties here
// attach the context
db.Employees.Attach(selectedEmployee);
// set modified state and save all changes
db.Entry(selectedEmployee).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
Related issues:
Why does Entity Framework reinsert existing objects into my database?
Updating the Record with EntityState.Modified but its inserting the new row rather than update

Querying DocumentDB for a list of propertiers using Linq's Select

Using Azure's DocumentDb and the .NET API, I have the following method which works great for retrieving lists of entire documents:
public async Task<IEnumerable<T>> GetItemsAsync<T>(Expression<Func<T, bool>> predicate)
{
IDocumentQuery<T> query = _Client.CreateDocumentQuery<T>(
UriFactory.CreateDocumentCollectionUri(_DatabaseId, _Collection),
new FeedOptions { MaxItemCount = -1 })
.Where(predicate)
.AsDocumentQuery();
List<T> results = new List<T>();
while (query.HasMoreResults)
{
var item = await query.ExecuteNextAsync<T>();
results.AddRange(item);
}
return results;
}
Now, I don't always want to return the entire document (especially considering the DocumentDb RU pricing model), so I thought I should be able to add a .Select projection like so:
public async Task<List<TResult>> GetItemsAsync<T, TResult>(Expression<Func<T, bool>> predicate, Expression<Func<T, TResult>> select)
{
IDocumentQuery<TResult> query = _Client.CreateDocumentQuery<T>(
UriFactory.CreateDocumentCollectionUri(_DatabaseId, _Collection),
new FeedOptions { MaxItemCount = -1 })
.Where(predicate)
.Select(select)
.AsDocumentQuery();
List<TResult> results = new List<TResult>();
while (query.HasMoreResults)
{
var item = await query.ExecuteNextAsync<TResult>();
results.AddRange(item);
}
return results;
}
Usage:
var rez = await _docs.GetItemsAsync<ApolloAssetDoc, Guid?>(x => x.MyVal == 5, x => x.ID);
But the second method always return 0 results. Obviously I'm barking up the wrong tree.
Any idea what the correct way to return a list of either dynamic objects for queries where more than one property is selected (eg "SELECT d.id, d.MyVal FROM Items d WHERE d.DocType=0")or a simple list where only a single property is selected (eg "SELECT d.id FROM Items d WHERE d.DocType=0")?
I could repro the issue, if there is no [JsonProperty(PropertyName = "id")] for ID property in the entity Class. If it is not included, please have a try to use the following code:
public class ApolloAssetDoc
{
[JsonProperty(PropertyName = "id")]
public Guid ID { get; set; }
public string MyVal { get; set; }
}
Note: The field is case sensitive.

Using CreateDocumentQuery to Azure DocumentDB to pass both field and value to query a collection

Assume I have a collection, with many documents, and I want to query that collection , where a field has a particular value. However, I do NOT know ahead of time which field we will be querying.
Here is an example of what I am trying to accomplish:
Document azureDocuments = client.CreateDocumentQuery(UriFactory.CreateDocumentCollectionUri(sDatabaseName, sCollectionCollection)).Where(f => f.MyField=MyValue).AsEnumerable().FirstOrDefault();
Has anyone done this successfully ?
Using CreateDocumentQuery to Azure DocumentDB to pass both field and value to query a collection
You could try to dynamically generate a predicate base on the fieldname and fieldvalue that user provides, and do filter based on the predicate. The following sample code is for your reference.
private async Task QueryDocs(string fieldname, string value)
{
Func<MyDoc, bool> criteria = d => d.id == d.id;
switch (fieldname)
{
case "id":
criteria = d => d.id == value;
break;
case "name":
criteria = d => d.name == value;
break;
//other cases...
}
string EndpointUri = "https://mydocumentdbtest.documents.azure.com:443/";
string PrimaryKey = "{primary key}";
DocumentClient client;
client = new DocumentClient(new Uri(EndpointUri), PrimaryKey);
var query = client.CreateDocumentQuery<MyDoc>(UriFactory.CreateDocumentCollectionUri("{databaseid}", "{collectionid}")).Where(criteria);
List<MyDoc> list = query.ToList();
}
public class MyDoc
{
public string id { get; set; }
public string name { get; set; }
}

CRM 2011: Custom Workflow Activity Output Parameters don´t show

everyone,
I'm having a problem that does not appear in the output parameter list on the right side under "Look for" underneath "Local Values", I do not understand the problem or reason for not appear, since in terms of input parameters's okay.
protected override void Execute(CodeActivityContext executionContext)
{
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
//Create the context
IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
tracingService.Trace("Creating Account");
Account entity = new Account();
entity.Name = AccountName.Get<string>(executionContext);
Guid entityId = service.Create(entity);
string a = entity.Name;
AccountNameTest.Set(executionContext, a);
tracingService.Trace("Account created with Id {0}", entityId.ToString());
tracingService.Trace("Create a task for the account");
Task newTask = new Task();
newTask.Subject = TaskSubject.Get<string>(executionContext);
newTask.RegardingObjectId = new EntityReference(Account.EntityLogicalName, entityId);
Guid taskId = service.Create(newTask);
tracingService.Trace("Task has been created");
tracingService.Trace("Retrieve the task using QueryByAttribute");
QueryByAttribute query = new QueryByAttribute();
query.Attributes.AddRange(new string[] { "regardingobjectid" });
query.ColumnSet = new ColumnSet(new string[] { "subject" });
query.EntityName = Task.EntityLogicalName;
query.Values.AddRange(new object[] { entityId });
tracingService.Trace("Executing the Query for entity {0}", query.EntityName);
//Execute using a request to test the OOB (XRM) message contracts
RetrieveMultipleRequest request = new RetrieveMultipleRequest();
request.Query = query;
Collection<Entity> entityList = ((RetrieveMultipleResponse)service.Execute(request)).EntityCollection.Entities;
//Execute a request from the CRM message assembly
tracingService.Trace("Executing a WhoAmIRequest");
service.Execute(new WhoAmIRequest());
if (1 != entityList.Count)
{
tracingService.Trace("The entity list was too long");
throw new InvalidPluginExecutionException("Query did not execute correctly");
}
else
{
tracingService.Trace("Casting the Task from RetrieveMultiple to strong type");
Task retrievedTask = (Task)entityList[0];
if (retrievedTask.ActivityId != taskId)
{
throw new InvalidPluginExecutionException("Incorrect task was retrieved");
}
tracingService.Trace("Retrieving the entity from IOrganizationService");
//Retrieve the task using Retrieve
retrievedTask = (Task)service.Retrieve(Task.EntityLogicalName, retrievedTask.Id, new ColumnSet("subject"));
if (!string.Equals(newTask.Subject, retrievedTask.Subject, StringComparison.Ordinal))
{
throw new InvalidPluginExecutionException("Task's subject did not get retrieved correctly");
}
//Update the task
retrievedTask.Subject = UpdatedTaskSubject.Get<string>(executionContext);
service.Update(retrievedTask);
}
}
//
[Input("Name conta")]
[Default("testv01")]
public InArgument<string> AccountName { get; set; }
[Input("Task")]
[Default("testv01")]
public InArgument<string> TaskSubject { get; set; }
[Input("Update task")]
[Default("testUPDATED:v01}")]
public InArgument<string> UpdatedTaskSubject { get; set; }
[Output("Account ID Guid")]
[Default("testUPDATED:v01")]
public OutArgument<string> AccountNameTest { get; set; }
Ok, problem solved, just restart IIS to assume the fields, or through version change. The problem was the update of the plugin, this also happens with workflows. According to CRM 4.0 i realized this situation does not happen in CRM 4.0.
Even though this Question is already answered I wanted to share two Cases where this solution didn't work (even in a recent Version of CRM):
Case 1
Having choosen Input-Parameter-Names that contained german Umlauts (äöüß).
IIS-restart did not help.
Choosing Names without Umlauts solved the Problem for me.
Case 2
We recently also had a case where a normal In-Argument did not show up, even after restarting the entire Maschine CRM was running on. The Solution was not to obvious:
Open PluginRegistrationTool from SDK
Choose the Assembly that contains your CWA
Choose your CWA
Hit the Save-Button in the Properties-Tab of your CWA

ServiceStack ORMLite

We are migrating our SProc based solution over to ORMLite, and so far has been pretty painless. Today I wrote the following method:
public AppUser GetAppUserByUserID(int app_user_id)
{
var dbFactory = new OrmLiteConnectionFactory(this.ConnectionString, SqlServerOrmLiteDialectProvider.Instance);
AppUser item = null;
var rh = new RedisHelper();
var id= CacheIDHelper.GetAppUserID( app_user_id );
item = rh.Get<AppUser>(id);
if (item == null)
{
try
{
using (var db = dbFactory.OpenDbConnection())
{
item = db.Single<AppUser>("application_user_id={0}", app_user_id);
rh.Set<AppUser>(item, id);
}
}
catch (Exception ex)
{
APLog.error(ex, "Error retrieving user!");
}
}
return item;
}
I have remove some of the extraneous fields, but they are basically:
[Alias("application_user")]
public class AppUser : APBaseObject
{
[Alias("application_user_id")]
[AutoIncrement]
public int? UserID
{
get;
set;
}
[Alias("application_user_guid")]
public string UserGUID
{
get;
set;
}
//MORE FIELDS here.
}
The challenge is that they only field that is populate is the ID field, AND I already know that ID because I am passing it into the method.
I did get the last SQL called and ran that against the DB directly and all of the fields were being referenced correctly.
I stepped through the code in the debugger, and everything came back correctly, except that the only field returned was the ID.
Thoughts?
I had a similar issue which was caused by my class methods not mapping to the db properly. My exact issue was caused by a nullable int field in the db and the class method was defined as an 'int' instead of 'int?'.
Perhaps you have a similar issue?

Resources