I am just wondering if it's possible to create some sort of binding without explicitly specifying all of the fields that need to be mapped to some widget(i.e. ListGrid).
Currently I do the following: First I read all the JSON objects fields and put these fields into CategoryRecord object like this:
public class CategoryRecord extends Record {
public CategoryRecord(String displayName, String id) {
setDisplayName(displayName);
setId(id);
}
private void setId(String id) {
setAttribute("id", id);
}
public String getId() {
return getAttributeAsString("id");
}
private void setDisplayName(String displayName) {
setAttribute("displayName", displayName);
}
public String getDisplayName() {
return getAttributeAsString("displayName");
}
}
Then I return a CategoryRecord[] object and put it into a ListGrid. But what if application developers decide to change the "id" field to "categoryId" or completely remove it. Do I have to manually change my code each time something like this happens? Or is there a way to get the whole JSON object, get it's fields and put it wherever I want, without specifying their names.
Thanks in advance!
Just iterate over the properties of the JSON object and create ListGridField objects for each one.
Related
The purpose of the project I'm working on is to handle annotation at compile time, it is not focused on what exactly I'm developing.
I took a simple subject for this and I'm writing a custom collection that will store elements and provide methods to manage them.
What I wanna do is to create an annotation #Contains, for example, to generate itemsContains method that could be processed while coding (instead of writing code manually).
public class Array {
private List<String> items;
public Array() {
items = Arrays.asList("abc", "def", "xyz");
}
public boolean itemsContains(String expected) {
return items.contains(expected);
}
}
Generally, I want my class to look something like:
public class Array {
#Contains
private List<String> items;
public Array() {
items = Arrays.asList("abc", "def", "111");
}
}
The important thing I want to reach is to have itemsContains method show up once the annotation is applied to a field. This is how it should look like:
expected result
Alternate existing examples are Lombok's #Getter/#Setter.
So what functionality or configurations should I implement to get the expected result?
Would be grateful for some real implementations or guides how to perform it step by step.
Annotation processing does not change the source file yet it generates a new file,
Lombok on the other hand does a trick to modify the source file itself, meaning that you need to call the generated class somewhere in your code.
One way to do this is to generate a class that extends the main class
#Generated
public class ArrayProxy extends Array {
public boolean itemsContains(String expected) {
return items.contains(expected);
}
}
and in your main class you need to do two things:
first you need to make items protected
you can add factory method to actually create the generated class
public class Array {
#Contains
protected List<String> items;
public static ArrayProxy create(){
return new ArrayProxy();
}
private Array() {
items = Arrays.asList("abc", "def", "111");
}
}
And of course you need to use it like this
ArrayProxy array = Array.create();
array.itemsContains("expected");
I have a configuration table in my database and it contains exactly one row.
ConfirmedScheduleColor | OverlappedScheduleColor | ColN
Currently, I'm retrieving the configuration like this:
var db = new SchedulingDbContext();
var config = db.Configurations.FirstOrDefault();
It's currently working fine and I can access my configurations and all. The thing is, the code looks awkward since I'm accessing the Configurations DbSet as if it contains many records (FirstOrDefault()); although actually, it contains only one record. I want to access my configurations like I'm accessing a static object. How to do that in EF?
You could simply add a property to your DbContext that returns Configurations.FirstOrDefault() and privatize the DbSet:
public class SchedulingDbContext : DbContext
{
private DbSet<Configuration> Configurations { get; set; }
public Configuration Configuration
{
get
{
return Configurations.FirstOrDefault();
}
}
}
I have a class in my project that has static methods to retrieve config settings. I use the ConfigurationManager rather than the database, but you could adapt it to get the setting from wherever you are storing the value.
In my example I have written a GetFromDb method for you that takes a key as parameter but that is because if I was storing my config settings in the database I wouldn't want to add a column every time I needed a new config setting. I would have a table with Key/Value columns. If you are wedded to the single row table then you might want to do without such a method.
public class Config
{
private _ConfirmedScheduleColor;
public static string ConfirmedScheduleColor
{
get
{
if(_ConfirmedScheduleColor == null)
_ConfirmedScheduleColor = GetFromDb("ConfirmedScheduleColor");
return _ConfirmedScheduleColor;
}
}
public static string OverlappedScheduleColor
{
get { return GetValue("OverlappedScheduleColor", "Pink"); }
}
public static int ColN
{
get { return GetValue("ColN", 2); }
}
private static string GetFromDb(string key)
{
if(key == "ConfirmedScheduleColor")
{
var config = db.Configurations.FirstOrDefault();
return config.ConfirmedScheduleColor;
}
}
private static string GetValue(string key, string defaultValue)
{
return ConfigurationManager.AppSettings[key] ?? defaultValue;
}
private static string GetValue(string key, int defaultValue)
{
int i;
if(int.TryParse(ConfigurationManager.AppSettings[key], out i))
return i;
return defaultValue;
}
}
In EF Core you can set the check constraint for the primary key. It enforces that column Id must have value that is equal to 1 which means only one record can exist in table if you have the primary key.
modelBuilder.Entity<YourTable>(e =>
{
e.HasCheckConstraint("CK_Table_Column", "[Id] = 1");
e.HasData(...) //optionally add some initial date for Id = 1
});
JSON Serialization (ASP.Net Web API) fails because of self-referencing loop (it’s a common problem, Reason: an entity being requested lazy loads child entities and every child has a back reference to parent entity).
Work around I found, but doesn’t help me:
Use [JsonIgnore] for navigation properties to be ignored:
This solution works but doesn’t apply in my case. For Example: To get a Customer information along with his Orders, I would quickly add [JsonIgnore] to Customer property in Order class, but when I want to get an Order information along with the Customer details, since there’s [JsonIgnore] on Customer property, it won’t include Customer details.
Change JSON.Net Serializer Settings to Preserve References:
Can’t Preserve because I don’t need Circular referenced data.
Disable Proxy Creation at the Data Context and use explicit loading(this should ideally solve the problem):
Disabling proxy creation stops Lazy Loading and returns data without error, but when I explicitly Include child entities, I again the get the unexpected self-referencing loop error! The error is at the back-reference level to parent entity.
Any experiences along the same lines/suggestions?
I tried all the suggested solutions but didn't work. Ended up with Overriding the JSON.Net Serializer’s DefaultContractResolver to this:
public class FilterContractResolver : DefaultContractResolver
{
Dictionary<Type, List<string>> _propertiesToIgnore;
public FilterContractResolver(Dictionary<Type, List<string>> propertiesToIgnore)
{
_propertiesToIgnore = propertiesToIgnore;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
List<string> toIgnore;
property.Ignored |= ((_propertiesToIgnore.TryGetValue(member.DeclaringType, out toIgnore) || _propertiesToIgnore.TryGetValue(member.DeclaringType.BaseType, out toIgnore)) && toIgnore.Contains(property.PropertyName));
return property;
}
}
Then created a Static Class which returns a dictionary of Properties to be Ignored based on the Controller:
public static class CriteriaDefination
{
private static Dictionary<string, Dictionary<Type, List<string>>> ToIgnore = new Dictionary<string, Dictionary<Type, List<string>>>
{
{
"tblCustomer", new Dictionary<Type, List<string>>{
{
typeof(tblCustomer), new List<string>{
//include all
}
},
{
typeof(tblOrder), new List<string>{
"tblCustomer"//ignore back reference to tblCustomer
}
}
}
},
{
"tblOrder", new Dictionary<Type, List<string>>{
{
typeof(tblCustomer), new List<string>{
"tblOrders"//ignore back reference to tblOrders
}
},
{
typeof(tblOrder), new List<string>{
//include all
}
}
}
}
};
public static Dictionary<Type, List<string>> IgnoreList(string key)
{
return ToIgnore[key];
}
}
And inside every controller change the JSON Formatter something like:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new FilterContractResolver(CriteriaDefination.IgnoreList("tblCustomer"));
This is what I ended up settling on, hopefully it helps someone else.
Say the EF classes are structured like this:
public partial class MyEF
{
public virtual ICollection<MyOtherEF> MyOtherEFs {get; set;}
}
public partial class MyOtherEF
{
public virtual MyEF MyEF {get; set;}
}
To keep serialization form happening in JSON.NET, you can extend the class and add a method with the name "ShouldSerialize" + property name like so:
public partial class MyEF
{
public bool ShouldSerializeMyOtherEFs() { return false; }
}
If you wanted to get a little more fancy, you could add logic in the method so that it would serialize in certain cases. This allows you to keep serialization logic out of the EF Model First code creation as long as this code is in a different physical code file.
Instead of letting the Entity Framework generate the model, use Code First with an existing database. Now you are more in control.
See this blog entry from Scott Guthrie
First of all, I have read this post and did not find the answer for my problem.
I am not sure if this is an aggregated Model class or an aggregated ViewModel class, but this is what I have:
In my WPF (with Prism) application, I have a view 'Filter Customers View' that connects to a service and requests a list of 'Customer' objects, based on a filter.
The list that is returned from the service is this :
List<CustomerDTO> FilteredCustomers;
And the CustomerDTO looks like this:
public class CustomerDTO
{
public Guid CustomerId;
public String Name;
public String Address;
public String PhoneNumber;
public OrderInfoDTO LastOrderInformation;
public List<OtherClass> ListOfSomething;
}
And the OrderInfoDTO looks like this:
public class OrderInfoDTO
{
public Guid OrderId;
public DateTime OrderDate;
public int NumberOfProducts;
public double TotalAmountSpent;
}
And the OtherClass looks like this:
public class OtherClass
{
public Guid Id;
public String SomeText;
}
As you can see - the customer might or might not have a 'Last Order',
I would like to wrap the 'CustomerDTO' object in a ViewModel,
so that I can bind it to the view.
This is what I thought of doing :
public class CustomerViewModel : NotificationObject
{
private CustomerDTO _customerDTO;
public CustomerViewModel(CustomerDTO customerDTO)
{
_customerDTO = customerDTO;
}
public Guid CustomerId
{
get { return _customerDTO.CustomerId; }
set { _customerDTO.CustomerId = value; RaisePropertyChanged("CustomerId "); }
}
public String Name
{
get { return _customerDTO.Name; }
set { _customerDTO.Name = value; RaisePropertyChanged("Name"); }
}
public String Address
{
get { return _customerDTO.Address; }
set { _customerDTO.Address = value; RaisePropertyChanged("Address"); }
}
public String PhoneNumber
{
get { return _customerDTO.PhoneNumber; }
set { _customerDTO.PhoneNumber= value; RaisePropertyChanged("PhoneNumber"); }
}
}
.
Questions:
First of all - is 'CustomerDTO' what is known as a Model ? And is 'OrderInfoDTO' also a Model ? and what about 'OtherClass' ?
How do I treat the 'OrderInfoDTO' in my CustomerViewModel class ? Do I create a 'ViewModel' for it also ? where do I create the 'OrderInfoDTO' view-model ??? What happens if now someone updates the customer and sets the 'OrderInfoDTO' value ?
How do I treat the list of 'OtherClass' in my CustomerViewModel class ? Do I create an ObservableCollection for it ? What happens if someone will want to delete an item in it or update an item in it or add an item to it ?
Think about it this way:
The View is your UI that you would bind elements from the View Model to using the {Binding Path=, Mode=TwoWay -- If you want to update based upon the user input
The Model is only the data, this could a record set, file, database records etc. So CustomerDTO and OrderInfoDTO are models.
The View Model is your link between the data (Model) and the UI (View). It will allow to you change the data so it's easier to present on the UI
You would need to use ObservableCollection in all instances where there's a list that could change in the background.
You don't need a view model for OrderInfoDTO unless you need a view to update that data. If you are presenting a CustomerDTO info with OrderInfoDTO in it, then making it a property of the CustomerDTO view model would be fine.
I have the following class hierarchy
[BsonKnownTypes(typeof(MoveCommand))]
public abstract class Command : ICommand
{
public abstract string Name
{
get;
}
public abstract ICommandResult Execute();
}
public class MoveCommand : Command
{
public MoveCommand()
{
this.Id = ObjectId.GenerateNewId().ToString();
}
[BsonId]
public string Id { get; set; }
public override string Name
{
get { return "Move Command"; }
}
public override ICommandResult Execute()
{
return new CommandResult { Status = ExecutionStatus.InProgress };
}
}
if I save the command like so:
Command c = new MoveCommand();
MongoDataBaseInstance.GetCollection<Command>("Commands").Save(c);
and then query the DB, I don't see the derived properties persisted.
{ "_id" : "4df43312c4c2ac12a8f987e4", "_t" : "MoveCommand" }
I would expect a Name property as a key in the document.
What am I doing wrong?
Also, is there a way to avoid having a BsonKnowTypes attribute on the base class for persisting derived instances? I don't see the why a base class needs to know about derived classes. This is bad OO design and is being forced on my class hierarchy by the BSON library. Am I missing something here?
1.Name property was not saved into database because it haven't setter. Serializers not serialize properties that's haven't setters (because if serializer serialize such property it will not able deserialize it back). So if you want serialize Name property then just add fake setter(into ICommand need to add it also):
public override string Name
{
get { return "Move Command"; }
set{}
}
2.If you don't want use BsonKnownTypes attribute there is another way to notify serializer about know types it might encounter during deserialization. Just Register maps once, on app start event:
BsonClassMap.RegisterClassMap<MoveCommand>();
//all other inherited from ICommand classes need register here also
So you should use or KnownTypes attribute or register BsonClassMap for each polymorphic class, otherwise you will get 'unknown descriminator' error during deserializtion:
var commands = col.FindAllAs<ICommand>().ToList();
3 You said:
This is bad OO design and is being
forced on my class hierarchy by the
BSON library.
In any way even without KnownTypes atribute your code using Bson lib through BsonId attribute.
If you want avoid it you can:
BsonClassMap.RegisterClassMap<MoveCommand>(cm => {
cm.AutoMap();
cm.SetIdMember(cm.GetMemberMap(c => c.Id));
});
So now you can remove reference to Mongodb.Bson lib from your domain code lib.