Is it possible to specify fields while doing a FindAndModify, so only one field is returned?
Also, is it possible to do an upsert, to create the object if it doesn't exist.
As per:
http://www.mongodb.org/display/DOCS/findAndModify+Command
I can't see any way of adding the additional arguments
EDIT:
Seems to be some confusion - I am using NoRM (C#)
https://github.com/atheken/NoRM/
I'm afraid it's not possible actually in NoRM. You could fork the project and add an overloaded FindAndModify method to the file NoRM/Collections/MongoCollectionGeneric.cs to support this behavior.
I think you might need to add a field fields in the anonymous object passed to findOne.
var returnValue = cmdColl.FindOne(new
{
findandmodify = this._collectionName,
query = query,
update = update,
sort = sort,
fields = fields
}).Value;
And maybe a pull request :)
Use the fields specifier. e.g.
db.foo.findAndModify({query:{_id:"myid"},
update:{$set:{priority:78}},new:true,fields:{_id:1,priority:1}})
Related
Context
I am using crmsvcutil to generate early bind entities. I am also utilizing entity name string constants MyEntity.EntityLogicalName for example in statements like the following (using alternate key):
var reference = new EntityReference(MyEntity.EntityLogicalName, "my_attribute_name", myValue)
Question
I would like to eliminate the "my_attribute_name" string literal in the statement. How can I do this?
Unfortunatelly I can not find it in the generated C# model.
Missed I something? If not, maybe there is an extension to crmsvcutil (similarly to the optionset generator sameple?
To answer the question, you can use the C# 6 nameof() expression to get the name of the property. If you convert the name to lower case, you end up with the logical name:
var logicalName = nameof(MyEntity.MyAttributeValue).ToLower();
With that being said, I rarely find myself having to do something like this. Often you can use Entity.ToEntityReference() for a more strongly typed approach.
Additionally the constructor you use for EntityReference is only meant to be used for alternate keys (otherwise one would just use the constructor that takes a string and a Guid)
I'm using v2.0 of the API via the C# dll. But this problem also happens when I pass a Query String to the v2.0 API via https://rally1.rallydev.com/slm/doc/webservice/
I'm querying at the Artifact level because I need both Defects and Stories. I tried to see what kind of query string the Rally front end is using, and it passes custom fields and built-in fields to the artifact query. I am doing the same thing, but am not finding any luck getting it to work.
I need to be able to filter out the released items from my query. Furthermore, I also need to sort by the custom c_ReleaseType field as well as the built-in DragAndDropRank field. I'm guessing this is a problem because those built-in fields are not actually on the Artifact object, but why would the custom fields work? They're not on the Artifact object either. It might just be a problem I'm not able to guess at hidden in the API. If I can query these objects based on custom fields, I would expect the ability would exist to query them by built-in fields as well, even if those fields don't exist on the Ancestor object.
For the sake of the example, I am leaving out a bunch of the setup code... and only leaving in the code that causes the issues.
var request = new Request("Artifact");
request.Order = "DragAndDropRank";
//"Could not read: could not read all instances of class com.f4tech.slm.domain.Artifact"
When I comment the Order by DragAndDropRank line, it works.
var request = new Request("Artifact");
request.Query = (new Query("c_SomeCustomField", Query.Operator.Equals, "somevalue").
And(new Query("Release", Query.Operator.Equals, "null")));
//"Could not read: could not read all instances of class com.f4tech.slm.domain.Artifact"
When I take the Release part out of the query, it works.
var request = new Request("Artifact");
request.Query = (((new Query("TypeDefOid", Query.Operator.Equals, "someID").
And(new Query("c_SomeCustomField", Query.Operator.Equals, "somevalue"))).
And(new Query("DirectChildrenCount", Query.Operator.Equals, "0"))));
//"Could not read: could not read all instances of class com.f4tech.slm.domain.Artifact"
When I take the DirectChildrenCount part out of the query, it works.
Here's an example of the problem demonstrated by an API call.
https://rally1.rallydev.com/slm/webservice/v2.0/artifact?query=(c_KanbanState%20%3D%20%22Backlog%22)&order=DragAndDropRank&start=1&pagesize=20
When I remove the Order by DragAndDropRank querystring, it works.
I think most of your trouble is due to the fact that in order to use the Artifact endpoint you need to specify a types parameter so it knows which artifact sub classes to include.
Simply adding that to your example WSAPI query above causes it to return successfully:
https://rally1.rallydev.com/slm/webservice/v2.0/artifact?query=(c_KanbanState = "Backlog")&order=DragAndDropRank&start=1&pagesize=20&types=hierarchicalrequirement,defect
However I'm not tally sure if the C# API allows you to encode additional custom parameters onto the request...
Your question already contains the answer.
UserStory (HierarchicalRequirement in WS API) and Defect inherit some of their fields from Artifact, e.g. FormattedID, Name, Description, LastUpdateDate, etc. You may use those fields in the context of Artifact type.
The fields that you are trying to access on Artifact object do not exist on it. They exist on a child level, e.g. DragAndDropRank, Release, Iteration. It is not possible to use those fields in the context of Artifact type.
Parent objects don't have access to attributes specific to child object.
Artifact is an abstract type.
If you need to filter by Release, you need to make two separate requests - one for stories, the other for defects.
I need to pass parameters to SQL statement, with Firebird ADO everything works well, but with InterBase ADO there is a problem.
My code:
result = conn.Query<DestClass>(sqlCmd, new
{
stringParam = stringVal,
intParam1 = intVal1,
intParam2 = intVal2
}).Single();
With that I've got FormatException, but when I define parameters with DynamicParameters and setting DbType.AnsiString for stringParam, SQL works well. But I've got many places in my code when I need to pass string and I don't want to change this in all places.
Then I found that I can use Dapper.SqlMapper.AddTypeMap(typeof(String), DbType.AnsiString);
but I can't. I've got Common Language Runtime detected an invalid program.
How to resolve this issue?
EDIT
It looks like problem is solved in Dapper v1.22.
There is a proposal to add an assembly-level attribute of the form:
[assembly:SomeName(blah)]
that would control the default string type for all types coming from that assembly. This would probably achieve most of what you need (although it would push the swing the other way, so you need to tell the other uses what to do). I am currently very actively hacking dapper, so I would expect this to materialize in the short term.
Note that you do not need to use DynamicParameters; you can also use:
stringParam = new DbString { Value = stringVal, IsAnsi = true }
I've been struggling for a while to find a way of calling an instance of a class from a user defined input.
Essentially I want to call an instance from my StandardVehicle class that has already been defined, however the problem is that the name of the instance that I'm calling is defined by a users selection on a combo box on a form.
This is how I assumed it would be formatted, however I get an error when I try calling the instance saying that I cannot complicitly convert from string to StandardVehicle.
StandardVehicle VauxhallB = new StandardVehicle();
VauxhallB.Model = "B";
VauxhallB.Manufacturer = "Vauxhall";
VauxhallB.Doors = 5;
VauxhallB.HorsePower = 200;
VauxhallB.Transmission = "Manual";
VauxhallB.Year = 2009;
VauxhallB.Cylinders = 6;
VauxhallB.Seats = 7;
VauxhallB.Price = 17000;
VauxhallB.Registration = "abc1243";
StandardVehicle objname = comboBox1.Text;
I'm assuming it's just a case of formatting the string, but I've been searching for hours and can't figure out what format it needs to be in to define it as an instance.
Any help would be appreciated.
Regards,
S.
No, it's definitely not a case of just formatting the string. It sounds like you want a
Dictionary<string, StandardVehicle>
Populate that to map from strings to objects, then look up the object corresponding to the name given by the user.
VauxhallB is just a symbol to the computer. The user shouldn't reference your variable names -- although it is probably possible to do so via reflection, but that's a complicated aspect of programming.
A better way to do this would be to associate each instance with a string "name" in a Dictionary<string, StandardVehicle>, and look up with that. Something like:
Dictionary<string, StandardVehicle> nameMap = new Dictionary<string, StandardVehicle>();
nameMap["VauxhallB"] = VauxhallB;
StandardVehicle objname = nameMap[comboBox1.Text];
Also, it's generally more readable if you only use lower case names for local variables, to better distinguish them from classes, public methods, and properties.
You cannot convert string to an object unless you have
Constructor that takes string and creates required object
An explicit/implicit cast operator
and another option
Use Activator.CreateInstace
3rd option is only valid if string contains valid type name, for your example you can do
Type type = Type.GetType(comboBox1.Text);
StandardVehicle objname = Activator.CreateInstace(type);
this will work if comboBox1.Text == "StandardVehicle".
More information here:
http://msdn.microsoft.com/en-us/library/w3f99sx1.aspx
http://msdn.microsoft.com/en-us/library/wccyzw83.aspx
Try this:
StandardVehicle selectedObject = (StandardVehicle)comboBox1.SelectedItem;
Of course, your comboBox should be bound to a collection of StandardVehicles... If it's not, then go for Dictionary as was already suggested.
First I also thought you mean reflection but you want to use your class StandardVehicle always. Just the properties should be set by a single string you receive from the user.
Write yourself a constructor. You define the format of the single string, for example fixed position within that string:
public StandardVehicle(String data)
{
this.Model = data.Substring(0, 1);
this.HorsePower = Int32.Parse(data.Substring(1, 4);
}
Not very comfortable but might work. Add some error handling. Or XML loading or other formats.
It's a little more complicated than your sample. I'm going to start with the quick and easy approach, which, while IS quick and easy, is kind of an anti-pattern, but I 'll explain that at the end:
IBritishAuto car;
switch
{
case "Vauxhall":
{
car = new Vauxhall(standardVehicle);
break;
}
case "Jaguar":
{
car = new Jaguar(standardVehicle);
}
...etc.
}
The reason why this is sub-optimal is that every time you want to add a new car type, you have to modify the original code block, and risk regression. If you're happy with this solution, and don't care, you can stop reading now.
Still there?
This pattern is called a "conditional dispatcher". There are two main strategies to improve it: refactor to a Command pattern (that's capped because it's a Gang of Four pattern), or a broader implementation of a concept called 'inversion of control'. If you're interested, here are your Google terms:
"refactor conditional dispatcher"
"inversion of control".
Good luck.
First off, I am new to programming (especially with C#) and thanks for your help.
I have a static web form with about 150 form objects (most checkboxes). I decided to go 1 record per form submission in the sql db. So, for example, question X has a choice of 5 checkboxes. Each of these 5 checkboxes has a column in the db.
I have the post page complete(working) and am building an edit page where I load the record and then populate the form.
How I am doing this is by passing a stored proc the id and then putting all the returned column values into the according object properties, then setting the asp control object to them.
An example of setting the asp controls to the selected value:
questionX.Items[0].Selected = selectedForm.questionX0
questionX.Items[1].Selected = selectedForm.questionX1
questionX.Items[2].Selected = selectedForm.questionX2
As you see, this is very tiresome since there are over 150 of these to do. Also, I just found out if the response is NULL then I get the error that it cant be converted to a string. So, I have added this line of code to get past it:
This is the part where I am populating the returned column values into the object properties (entity is the object):
if (!String.IsNullOrEmpty((string)reader["questionX0"].ToString()))
{entity.patientUnderMdTreatment = (string)reader["questionX0"];}
So, instead of having to add this if then statement 150+ times. There must be a way to do this more efficiently.
First of all, it seems that you are using string.IsNullOrEmpty(value), but this won’t check for the special DBNull value that is returned from databases when the data is null. You should use something more akin to value is DBNull.
The rest of your problem sounds complex, so please don’t be put off if my answer is complex too. Personally I would use custom attributes:
Declare a custom attribute
The following is a skeleton to give you the idea. You may want to use the “Attribute” code snippet in Visual Studio to find out more about how to declare these.
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public sealed class QuestionColumnAttribute : Attribute
{
public string ColumnName { get; private set; }
public QuestionColumnAttribute(string columnName)
{
ColumnName = columnName;
}
}
Use the custom attribute in the entity class
Where you declare your entity class, add this custom attribute to every field, for example where patientUnderMdTreatment is declared:
[QuestionColumn("questionX0")]
public string patientUnderMdTreatment;
Iterate over the fields
Instead of iterating over the columns in the reader, iterate over the fields. For each field that has a QuestionColumnAttribute on it, get the relevant column from the reader:
foreach (var field in entity.GetType().GetFields())
{
var attributes = field.GetCustomAttributes(typeof(QuestionColumnAttribute), true);
if (attributes.Length == 0)
continue;
object value = reader[attributes[0].ColumnName];
if (!(value is DBNull))
field.SetValue(entity, value.ToString());
}
For the first part of your question where you set the ASP controls, you can use a similar strategy iterating over the fields of selectedForm, and this is probably simpler because you don’t need a custom attribute — just take only the fields whose name starts with “questionX”.
this is a quick & easy way of doing it.. there are some suggestions to investigate LINQ, and I'd go with those first.
for (int i = 0; i < 150; i++)
{
if (!String.IsNullOrEmpty((string)reader["questionX" + i.ToString()].ToString()))
{entity.patientUnderMdTreatment = (string)reader["questionX" + i.ToString()];}
}
... though this wouldn't be any good with the
questionX.Items[0].Selected = selectedForm.questionX0
questionX.Items[1].Selected = selectedForm.questionX1
questionX.Items[2].Selected = selectedForm.questionX2
lines
so I hear two questions:
- how to deal with null coming from IDataReader?
- how to deal with multiple fields?
Lets start with simple one. Define yourself a helper method:
public static T IsDbNull<T>(object value, T defaultValue)
{
return (T)(value is DBNull ? defaultValue : value);
}
then use it:
entity.patientUnderMdTreatment = IsDbNull<string>(reader["question"], null);
Now how to map entity fields to the form? Well that really is up to you. You can either hardcode it or use reflection. The difference of runtime mapping vs compile-time is likely to be completely irrelevant for your case.
It helps if your form fields have identical names to ones in the DB, so you don't have to do name mapping on top of that (as in Timwi's post), but in the end you'll likely find out that you have to do validation/normalization on many of them anyway at which point hardcoding is really what you need, since there isn't a way to dynamically generate logic according to the changing spec. It doesn't matter if you'll have to rename 150 db fields or attach 150 attributes - in the end it is always a O(n) solution where n is number of fields.
I am still a little unsure why do you need to read data back. If you need to preserve user's input on form reload (due to validation error?) wouldn't it be easier/better to reload them from the request? Also are entity and selectedForm the same object type? I assume its not a db entity (otherwise why use reader at all?).
Its possible that there are some shortcuts you may take, but I am having hard time following what are you reading and writing and when.
I recommend using the NullableDataReader. It eliminates the issue.