Generic List is not being inserted into MongoDB - c#

I'm trying to insert a protobuf-net object into my MongoDB. The object looks something like this:
message Measurement
{
optional string _someString1 = 1 [default = ""];
optional string _someString2 = 2 [default = ""];
repeated MyMessage1 _myMessages1 = 3;
repeated MyMessage2 _myMessages2 = 4;
repeated MyMessage3 _myMessages3 = 5;
}
MyMessage1..3 are messages in the same proto file and they contain a few strings, doubles and int64s.
I fill an instance of Measurement with some data and try to insert it into my DB, like this:
var col = MyDatabase.GetCollection<Measurement>("Measurements");
col.Insert(instanceOfMeasurement);
Now, if I check on the contents of the DB, I can see that the instanceOfMeasurement has been added correctly. But the repeated fields within haven't. Do I need to prepare a more complex object in some way, before stuffing it into MongoDB?
Okay, here is what protobuf-net creates:
[global::System.Serializable, global::ProtoBuf.ProtoContract(Name=#"Measurement")]
public partial class Measurement : global::ProtoBuf.IExtensible, global::System.ComponentModel.INotifyPropertyChanged
{
public Measurement() {}
private string __someString1;
[global::ProtoBuf.ProtoMember(1, IsRequired = false, Name=#"_someString1", DataFormat = global::ProtoBuf.DataFormat.Default)]
public string _SomeString1
{
get { return __someString1?? ""; }
set { __someString1 = value; OnPropertyChanged(#"_someString1"); }
}
[global::System.Xml.Serialization.XmlIgnore]
[global::System.ComponentModel.Browsable(false)]
public bool _someString1Specified
{
get { return this.__someString1 != null; }
set { if (value == (this.__someString1== null)) this.__someString1 = value ? this._someString1 : (string)null; }
}
private bool ShouldSerialize_someString1() { return _someString1Specified; }
private void Reset_someString1() { _someString1Specified = false; }
private string __someString2;
[global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=#"_someString2", DataFormat = global::ProtoBuf.DataFormat.Default)]
public string _SomeString2
{
get { return __someString2?? ""; }
set { __someString2 = value; OnPropertyChanged(#"_someString2"); }
}
[global::System.Xml.Serialization.XmlIgnore]
[global::System.ComponentModel.Browsable(false)]
public bool _someString2Specified
{
get { return this.__someString2 != null; }
set { if (value == (this.__someString2== null)) this.__someString2 = value ? this._someString2 : (string)null; }
}
private bool ShouldSerialize_someString2() { return _someString2Specified; }
private void Reset_someString2() { _someString2Specified = false; }
private readonly global::System.Collections.Generic.List<MyMessage1> __myMessages1 = new global::System.Collections.Generic.List<MyMessage1>();
[global::ProtoBuf.ProtoMember(6, Name=#"_myMessages1", DataFormat = global::ProtoBuf.DataFormat.Default)]
public global::System.Collections.Generic.List<MyMessage1> _myMessages1
{
get { return __myMessages1; }
}
private readonly global::System.Collections.Generic.List<MyMessage2> __myMessages2 = new global::System.Collections.Generic.List<MyMessage2>();
[global::ProtoBuf.ProtoMember(7, Name=#"_myMessages2", DataFormat = global::ProtoBuf.DataFormat.Default)]
public global::System.Collections.Generic.List<MyMessage2> _myMessages2
{
get { return __myMessages2; }
}
private readonly global::System.Collections.Generic.List<MyMessage3> __myMessages3 = new global::System.Collections.Generic.List<MyMessage3>();
[global::ProtoBuf.ProtoMember(8, Name=#"_myMessages3", DataFormat = global::ProtoBuf.DataFormat.Default)]
public global::System.Collections.Generic.List<MyMessage3> _myMessages3
{
get { return __myMessages3; }
}
public event global::System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{ if(PropertyChanged != null) PropertyChanged(this, new global::System.ComponentModel.PropertyChangedEventArgs(propertyName)); }
private global::ProtoBuf.IExtension extensionObject;
global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
{ return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); }
}

The driver doesn't by default serialize properties that have no setter. Evidently that includes the messages on Measurement.
To override the default behavior and include these properties* you either mark them with the BsonElement attribute or map them with RegisterClassMap. In this case where the classes are auto-generated an attribute would be a bad idea so use the latter:
BsonClassMap.RegisterClassMap<Measurement>(m =>
{
m.MapProperty(x => x.MyMessage1);
m.MapProperty(x => x.MyMessage2);
m.MapProperty(x => x.MyMessage3);
});
More in Serialize Documents with the C# Driver: Opt In
* When a readonly property is serialized, it value is persisted to the database, but never read back out. This is useful for storing “computed” properties

Related

Best way to override ext.net combobox

I try to find some examples for overriding ext.net combobox. I need to do this, because I want to use default values for most properties. But I have a problem. I could not to find some examples for store, handler, proxy and my own listeners which using in combobox. How can I override it? Can anybody give me some examples?
A C# class example for own combobox. My thanks.
Edit...
public class CombinedComboBox : ComboBox
{
#region Properties
private string _handlerAddress;
private Store _store;
private StoreParameterCollection _storeParameters;
private ModelFieldCollection _modelFields;
private ListenerCollection _listeners;
public string HandlerAddress
{
get { return _handlerAddress; }
set
{
if (!value.StartsWith("/Handlers/"))
_handlerAddress = "/Handlers/" + value;
else
_handlerAddress = value;
}
}
public StoreParameterCollection StoreParameters
{
get { return _storeParameters; }
set { _storeParameters = value; }
}
public ModelFieldCollection ModelFields
{
get { return _modelFields; }
set { _modelFields = value; }
}
#endregion
#region ASP.NET Controls Init & Events
public CombinedComboBox()
{
//Базовые автоматические значения, также можно просадить в Init
HideLabel = false;
DisplayField = "Name";
PageSize = 10;
TypeAhead = true;
LabelWidth = 160;
MinChars = 2;
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
BuildStore();
if (!AllowBlank) AfterLabelTextTpl.Html = "<span style=\"color: red; font - weight: bold\" data-qtip=\"Required\">*</span>";
}
private void BuildStore()
{
_store = new Store
{
AutoLoad = false,
RemotePaging = true,
RemoteFilter = true,
IsPagingStore = true,
PageSize = PageSize
};
_store.Proxy.Add(new AjaxProxy
{
Json = true,
ActionMethods = { Read = HttpMethod.GET },
Url = HandlerAddress,
Reader = { new JsonReader { Root = "data", TotalProperty = "total" } }
});
if (_storeParameters != null && _storeParameters.Count > 0)
{
foreach (var item in _storeParameters)
{
_store.Parameters.Add(item);
}
}
_store.AutoLoadParams.Add(new Parameter("start", "0"));
_store.AutoLoadParams.Add(new Parameter("limit", PageSize.ToString()));
Model model = new Model { IDProperty = "Id" };
model.Fields.Add(new ModelField("Id", ModelFieldType.String));
model.Fields.Add(new ModelField("Name", ModelFieldType.String));
if (_modelFields != null && _modelFields.Count > 0)
{
foreach (var item in _modelFields)
{
model.Fields.Add(item);
}
}
_store.Model.Add(model);
Bin.Add(_store);
}
#endregion
}
My WebForm:
<elem:CombinedComboBox
ID="MyId"
runat="server"
EmptyText="Text"
FieldLabel="Text"
HandlerAddress="/Handlers/OrgStructureDirectionsListHandler.ashx">
<StoreParameters>
<ext:StoreParameter Name="DirectionType" Value="SomeDirection" Mode="Value" />
</StoreParameters>
<Listeners>
<Select Fn="ItemSelected"/>
</Listeners>
</elem:CombinedComboBox>
But Handler never called. Why?
Ok, I found a problem. It was because I didn't place ID for my store like this:
protected override void OnPreRender(EventArgs e)
{
StoreID = _store.ClientID;
base.OnPreRender(e);
}

.NET bind checked property of checkbox with SqlByte datatype

This fails:
dtaAutomaticFlag.DataBindings.Add("Checked", BndSource, "AutomaticFlag");
most probably because AutomaticFlag is defined as:
public SqlByte AutomaticFlag { get; set; }
SQL Server is tinyint. The reason is that i dont only need 0 and 0 as values.
I need to be checked if the value is 1 , unchecked for ALL other values.
One thing that i thought is to create an extra property AutomaticFlagBoolean in my class and check the AutomaticFlag and bind to the new property.
This is what i tried but i get always false:
private SqlByte _automaticFlag;
public SqlByte AutomaticFlag
{
get { return _automaticFlag; }
set
{
if (_automaticFlagBoolean)
{
_automaticFlag = 1;
}
else
{
_automaticFlag = 0;
}
}
}
private bool _automaticFlagBoolean;
public bool AutomaticFlagBoolean
{
get
{
if (_automaticFlag == 1)
{
return _automaticFlagBoolean = true;
}
else
{
return _automaticFlagBoolean = false;
}
}
set { _automaticFlagBoolean = value; }
}
this is in my binding:
dtaAutomaticFlag.DataBindings.Add("Checked", BndSource, "AutomaticFlagBoolean");
The checkbox control expects a boolean value for binding.
Try using a local variable to hold the value:
private SqlByte _automaticFlag;
private bool _automaticFlagBoolean;
public SqlByte AutomaticFlag
{
get { return _automaticFlag; }
set
{
_automaticFlag = value;
_automaticFlagBoolean = (_automaticFlag != 0);
}
}
public bool AutomaticFlagBoolean
{
get
{
return _AutomaticFlagBookean;
}
set { _automaticFlagBoolean = value;
if (_automaticFlagBoolean) {
_automaticFlag = 1;
} else {
_automaticFlag = 0;
}
}
}
Then bind as so:
dtaAutomaticFlag.DataBindings.Add("Checked", BndSource, "AutomaticFlagBoolean");
Your class should also implement INotifyPropertyChanged as well but that's a little beyond the scope of your question.

Return all the fields from a class

I am attempting to cycle through the Fields in my class, place the fields of a certain type into a list and then return that list. I know I am missing some key component but I cannot figure out what I am doing wrong. This is what I have so far:
...
I need to return a list of the actual fields as pointers, not a copy of the data. Any help in getting this to work would be appreciated.
I removed the above code (you should still be able to see it in the history) because it was confusing. This is the updated code (with some extra stuff removed) that works thanks to the answer from competent_tech:
string prop1;
BaseClass prop2;
SubClass prop3;
SubClass prop4;
public List<BaseClass> GetData()
{
List<BaseClass> DataList = new List<BaseClass>();
foreach (System.Reflection.PropertyInfo thisInfo in this.GetType().GetProperties())
{
var tempPropery = thisInfo.GetValue(this, null);
if (tempPropery.GetType().IsSubclassOf(typeof(BaseClass)) || tempPropery.GetType().Equals(typeof(BaseClass)))
{
DataList.Add((BaseClass)tempPropery);
};
}
return DataList;
}
The above code will allow you to get all the properties of a specific base type from your class and return them in a list. So the above code would return prop2 - prop4.
You can accomplish this through reflection.
foreach (System.Reflection.PropertyInfo oProperty in this.GetType().GetProperties()) {
}
There are numerous ways that you can use this information once you have it or filter the properties (for example, by adding an attribute to the properties that you want to collect).
You can get more information from MSDN.
Note that this code specifically references properties, but there are equivalent methods for retrieving fields (GetFields) and all members (GetMembers).
Once you have the PropertyInfo, you can call the GetValue method:
foreach (System.Reflection.PropertyInfo oProperty in this.GetType().GetProperties()) {
Console.WriteLine(oProperty.Name + " = " + oProperty.GetValue(this, null).ToString());
}
Alternatively, if you are looking at both fields and properties:
foreach (System.Reflection.MemberInfo oMember in this.GetType().GetMembers())
{
switch (oMember.MemberType)
{
case System.Reflection.MemberTypes.Field:
var oField = (System.Reflection.FieldInfo)oMember;
Console.WriteLine(oField.Name + " = " + oField.GetValue(this).ToString());
break;
case System.Reflection.MemberTypes.Property:
var oProperty = (System.Reflection.PropertyInfo)oMember;
Console.WriteLine(oProperty.Name + " = " + oProperty.GetValue(this, null).ToString());
break;
}
}
You can store data in Dictionary. For every property only set/get value from dictionary.
Something like this:
public class MyData {
private Dictionary<string, object> myData;
public MyData {
this.myData = new Dictionary<string, object>();
}
public decimal LastVersion { get { return (decimal)this.myData["LastVersion"]; } private set { this.myData["LastVersion"] = value; } }
public PrimaryAbility STR { get { return (PrimaryAbility)this.myData["STR"]; } private set { this.myData["STR"] = value; } }
public PrimaryAbility DEX { get { return (PrimaryAbility)this.myData["DEX"]; } private set { this.myData["DEX"] = value; } }
public PrimaryAbility CON { get { return (PrimaryAbility)this.myData["CON"]; } private set { this.myData["CON"] = value; } }
public PrimaryAbility INT { get { return (PrimaryAbility)this.myData["INT"]; } private set { this.myData["INT"] = value; } }
public PrimaryAbility WIS { get { return (PrimaryAbility)this.myData["WIS"]; } private set { this.myData["WIS"] = value; } }
public PrimaryAbility CHA { get { return (PrimaryAbility)this.myData["CHA"]; } private set { this.myData["CHA"] = value; } }
public DerivedAbility HP { get { return (DerivedAbility)this.myData["HP"]; } private set { this.myData["HP"] = value; } }
public DerivedAbility MP { get { return (DerivedAbility)this.myData["MP"]; } private set { this.myData["MP"] = value; } }
public DerivedAbility SP { get { return (DerivedAbility)this.myData["SP"]; } private set { this.myData["SP"] = value; } }
public DerivedAbility AC { get { return (DerivedAbility)this.myData["AC"]; } private set { this.myData["AC"] = value; } }
}
Some day I found this: "Enum.GetValues(typeof(TvStations))", maybe you should search some like this.

How can I match custom PropertyGrid BrowsableAttributes entries?

I have a class(KeywordProperties) with this code :
public class KeywordProperties
{
[DisplayMode("0-1,0-2,0-3,1-1,1-2,1-3,1-6,1-9,1-10,1-11,1-12,2-1,2-2,2-3,2-9,2-10,2-12,3-1,3-2,3-3,3-10,3-12,4-13,5,6")]
public string Onvaan { get; set; }
[DisplayMode("0-1,0-2,0-3,1-1,1-2,1-3,1-6,1-9,1-10,1-11,1-12,2-1,2-2,2-3,2-9,2-10,2-12,3-1,3-2,3-3,3-10,3-12,4-13,5,6")]
public string MozooKolli { get; set; }
[DisplayMode("0-10,1-10,3-10,3-12,5,6")]
public string EsmeDars { get; set; }
[DisplayMode("0-1,1-1,2-1,2-2,3-1,6")]
public string Sokhanraan { get; set; }
[DisplayMode("0-10,1-2,2-1,2-10,3-10,6")]
public string Modares { get; set; }
}
And I have another for check attributes :
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class DisplayModeAttribute : Attribute
{
private readonly string mode;
public DisplayModeAttribute(string mode)
{
this.mode = mode ?? "";
}
public override bool Match(object obj)
{
var other = obj as DisplayModeAttribute;
if (other == null) return false;
if (other.mode == mode) return true;
// allow for a comma-separated match, in either direction
if (mode.IndexOf(',') >= 0)
{
string[] tokens = mode.Split(',');
if (Array.IndexOf(tokens, other.mode) >= 0) return true;
}
else if (other.mode.IndexOf(',') >= 0)
{
string[] tokens = other.mode.Split(',');
if (Array.IndexOf(tokens, mode) >= 0) return true;
}
return false;
}
}
I want display properties in propertygrid with this code :
String Code = "":
KeywordProperties Kp = new KeywordProperties();
propertygrid1.SelectedObject = Kp;
propertygrid1.BrowsableAttributes = new AttributeCollection(new DisplayModeAttribute(Code));
When Code vlue is "0-1" or "5" or ...(single value), I can see my properties.
But, when use "0-1,1-2" for Code, I can't see any thing in my properygrid.
How can I see these data :
1- All properties that have code 0-1 and code 1-2 :
result is :Onvaan,MozooKolli
2- All properties that have code 0-1 or code 1-2 :
result is : Onvaan,MozooKolli,Sokhanraan,Modares
It appears that your code only matches DisplayModeAttributes when both have a single value, or one contains a single value and the other contains multiple values; it won't match them when both contain multiple values, unless the list of values are identical.
To use your code as-is, you could change the way you populate PropertyGrid.BrowsableAttributes:
propertygrid1.BrowsableAttributes = new AttributeCollection(
new DisplayModeAttribute("0-1"),
new DisplayModeAttribute("1-2")
// etc.
);
Alternatively, to fix your matching code, you could replace it with something like:
public override bool Match(object obj)
{
var other = obj as DisplayModeAttribute;
if (other == null)
return false;
if (other.mode == mode)
return true;
string[] modes = mode.Split(',');
string[] others = other.mode.Split(',');
var matches = modes.Intersect(others);
return matches.Count() > 0;
}
This uses the LINQ Intersect method, which returns the elements that two lists have in common.

RaisePropertyChanged not updating UI

I'm having trouble getting my UI to update Two Listboxes' to update properly when my ViewModel changes.
First, the basic logic behind the page:
Movie is an object with a title, and a variety of MovieDetails. Some MovieDetail are different than others, as they are detailed which is a glorified way of saying they're more Important.
I use two ListBoxes to separate these MovieDetails into stacked ListBoxes, one for 'Detailed' and one for 'NotDetailed'
If a movie has no 'Detailed' attributes, the corresponding list is Hidden via a BooleanToVisibilityConverter (and vice-versa)
When I navigate to the page, I set the Movie the page corresponds to, and it should RaisePropertyChanged to alert the AllMoviesDetail ObservableCollection that it should re-get Movies.MovieDetailFetchedList.
From there, AllMoviesDetail would alert the two ObservableCollections (Detailed, NotDetailed) they should be re-get.
In fact, RaisePropertyChanged on NotDetailedMovieDetails or DetailedMovieDetails does not seem to do anything either. (And the corresponding HasNotDetailedMovieDetails, Has...)
What does work, however, is if I add more items into the list, the CollectionChanged event seems to fire and reactivate the list. I have also been able to do this by instantiating the ObservableCollections in code first var temp = DetailedMoviesDetail;
public class MoviesDetailViewModel : ViewModelBase
{
#region Property Names
public const string MoviePropertyString = "Movie";
public const string AllMoviesDetailPropertyString = "AllMoviesDetail";
public const string DetailedMoviesDetailPropertyString = "DetailedMoviesDetail";
public const string NotDetailedMoviesDetailPropertyString = "NotDetailedMoviesDetail";
public const string HasNotDetailedMoviesDetailPropertyString = "HasNotDetailedMoviesDetail";
public const string HasDetailedMoviesDetailPropertyString = "HasDetailedMoviesDetail";
public const string NotDetailedHeaderPropertyString = "NotDetailedHeader";
#endregion
public MoviesDetailViewModel()
{
if (IsInDesignMode)
{
Movie = DesignDataStore.MovieList[0];
Movie.Category = Category.DDA;
}
}
private Movie _Movie;
/// <summary>
/// The Movie for which to browse MoviesDetail. It is expected when setting this property, that MoviesDetail for it have been downloaded previously.
/// </summary>
/// <remarks>The 'Master' property for this ViewModel. All properties are Dependent on this and the underlying property MoviesDetailList</remarks>
/// <seealso cref="MovieDetailFetchedList"/>
public Movie Movie
{
get { return _Movie; }
set
{
if (_Movie != value)
{
if (_Movie != null)
_Movie.MovieDetailFetchedList.CollectionChanged -= MoviesDetailListChanged;
_Movie = value;
RaisePropertyChanged(MoviePropertyString);
RaisePropertyChanged(StatementPeriodAvailablePropertyString);
RaisePropertyChanged(NotDetailedMoviesDetailPropertyString);
Movie.MovieDetailFetchedList.CollectionChanged += MoviesDetailListChanged;
RaisePropertyChanged(AllMoviesDetailPropertyString);
RaisePropertyChanged(DetailedMoviesDetailPropertyString);
RaisePropertyChanged(NotDetailedHeaderPropertyString);
}
}
}
private void MoviesDetailListChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var item in e.NewItems)
{
if (((MovieDetail) item).IsDetailed())
DetailedMoviesDetail.Add(item as MovieDetail);
else
NotDetailedMoviesDetail.Add(item as MovieDetail);
}
}
else
{
RaisePropertyChanged(AllMoviesDetailPropertyString);
RaisePropertyChanged(DetailedMoviesDetailPropertyString);
RaisePropertyChanged(NotDetailedMoviesDetailPropertyString);
}
}
#endregion
private MovieDetailFetchedList _allMoviesDetail;
public MovieDetailFetchedList AllMoviesDetail
{
get
{
if (Movie == null)
return new MovieDetailFetchedList();
return _allMoviesDetail ?? (AllMoviesDetail = Movie.MovieDetailFetchedList);
}
set
{
if (_allMoviesDetail != value)
{
if (_allMoviesDetail != null)
_allMoviesDetail.CollectionChanged -= MoviesDetailListChanged;
_allMoviesDetail = value;
_allMoviesDetail.CollectionChanged += MoviesDetailListChanged;
RaisePropertyChanged(AllMoviesDetailPropertyString);
//force update
DetailedMoviesDetail = NotDetailedMoviesDetail = null;
RaisePropertyChanged(DetailedMoviesDetailPropertyString);
RaisePropertyChanged(HasDetailedMoviesDetailPropertyString);
RaisePropertyChanged(NotDetailedMoviesDetailPropertyString);
RaisePropertyChanged(HasNotDetailedMoviesDetailPropertyString);
}
}
}
public bool HasNotDetailedMoviesDetail { get { return NotDetailedMoviesDetail != null && NotDetailedMoviesDetail.Count > 0; } }
private ObservableCollection<MovieDetail> _notDetailedMoviesDetail;
public ObservableCollection<MovieDetail> NotDetailedMoviesDetail
{
get
{
if (Movie == null) return new ObservableCollection<MovieDetail>();
return AllMoviesDetail;
return _notDetailedMoviesDetail ?? //make sure RaisePropertyChanged happens by using property setter
(NotDetailedMoviesDetail = AllMoviesDetail.Where(mem => !mem.IsDetailed()).ToObservableCollection());
}
set
{
_notDetailedMoviesDetail = value;
RaisePropertyChanged(NotDetailedMoviesDetailPropertyString);
RaisePropertyChanged(HasNotDetailedMoviesDetailPropertyString);
}
}
public bool HasDetailedMoviesDetail
{ get { return DetailedMoviesDetail != null && DetailedMoviesDetail.Count > 0; } }
private ObservableCollection<MovieDetail> _DetailedMoviesDetail;
public ObservableCollection<MovieDetail> DetailedMoviesDetail
{
get
{
if (Movie == null) return new ObservableCollection<MovieDetail>();
return AllMoviesDetail;
return _DetailedMoviesDetail ?? //make sure RaisePropertyChanged happens by using property setter
(DetailedMoviesDetail = AllMoviesDetail.Where(mem => mem.IsDetailed()).ToObservableCollection());
}
set
{
_DetailedMoviesDetail = value;
RaisePropertyChanged(DetailedMoviesDetailPropertyString);
RaisePropertyChanged(HasDetailedMoviesDetailPropertyString);
}
}
private string _DetailedHeader;
public string DetailedHeader
{
get { return _DetailedHeader ?? (_DetailedHeader = AppResources.in_available); }
set { _DetailedHeader = value; }
}
public string NotDetailedHeader
{
get { return (Movie != null && Movie.Category == Category.DRAMA) ? AppResources.Movie_MoviesDetail : AppResources.not_in_available; }
}
}
All of your property getters (except AllMoviesDetail) have two return statements. Since only the first will be executed, the values are not being assigned and the PropertyChanged events are not being twiggered.

Categories

Resources