I have a table with the columns IsActive and CanBeUsed (don't ask why, it's not my choice). I want my entity to have one field called isWorkable that is done from those two fields. How can i do this?
The only thing I can think of is to do:
[Table(Name = "Task")]
public class Task
{
...elided...
private string IsActive;
[Column(Storage = "IsActive")]
public string activeState
{
get
{
return this.IsActive;
}
set
{
this.IsActive = value;
}
}
private string CanBeUsed;
[Column(Storage = "CanBeUsed")]
public string useState
{
get
{
return this.CanBeUsed;
}
set
{
this.CanBeUsed = value;
}
}
private bool isWorkable
{
get
{
return this.IsActive == "Y" && this.CanBeUsed == "Y";
}
}
}
But I would prefer that the two fields from the DB either are private (no public getter/setter) or don't exist and I can somehow make a custom setter that maps to two columns for isWorkable.
Is that possible?
Related
I'm trying to implement a PATCH on Web API for an object that will be stored in a DB. The input object from the controller has all of the properties that can be modified but we allow the client to choose which fields to send back. We only want to update the MongoDB representation if some of the fields have changed or been set. We started using a Dirty object pattern (not sure this is a pattern) whereby when you set a property you also record that it is dirty. for instance
public class Example
{
private string _title;
public string Title
{
get { return _title; }
set
{
_title = value;
TitleWasSet = true;
}
}
public bool TitleWasSet {get;set;}
}
This could work but is kind of tedious and I feel it exposes lots of logic that could be contained.
So a solution I came up with was to store the update Actions in the inbound object then reapply them to the Mongo Object in a Try Update fashion.
like this:
public class Data
{
public string Header { get; set; }
public int Rating { get; set; }
}
public class EditDataRequest
{
private readonly List<Action<Data>> _updates;
public EditDataRequest()
{
_updates = new List<Action<Data>>();
}
public string Header
{
set
{
_updates.Add(data => {data.Header = value;});
}
}
public int Rating
{
set
{
_updates.Add(data => {data.Rating = value;});
}
}
public bool TryUpdateFromMe(Data original)
{
if (_updates.Count == 0)
return false;
foreach (var update in _updates)
{
update.Invoke(original);
}
return true;
}
}
Now this would work great but it doesn't take account of the values being the same. So i then looked at changing the list of actions to a list of functions that would return a bool if there was a difference in the value.
private readonly List<Func<Data, bool>> _updates;
And then the properties would look like this:
public int Rating
{
set
{
_updates.Add(data => {
if (data.Rating != value)
{
data.Rating = value;
return true;
}
return false;
});
}
}
And the try update method...
public bool TryUpdateFromMe(Data original)
{
if (_updates.Count == 0)
return false;
bool changesRequired = false;
foreach (var update in _updates)
{
changesRequired |= update.Invoke(original);
}
return changesRequired;
}
As you can see that property set implementation is rather clunky and would make the code nasty to read.
I'd like a way of extracting the check this property value then update it to another method that I can reuse in each property - I assume this is possibly somehow but it might not be.
Of course, if you have better suggestions for how to handle the PATCH situation then I'd be happy to hear them as well.
Thanks for reading this far.
I have a class that is used for storing user data to a file. It works well, but can't really be placed into a PCL library easily. Outside of the PCL, it's all fine.
The class looks like this
public static class UserData
{
public static object GetPropertyValue(this object data, string propertyName)
{
return data.GetType().GetProperties().Single(pi => pi.Name == propertyName).GetValue(data, null);
}
public static object SetPropertyValue<T>(this object data, string propertyName, T value)
{
data.GetType().GetProperties().Single(pi => pi.Name == propertyName).SetValue(data, value);
return new object();
}
private static string pUserSettingsFile;
private static UserSettings userSetting;
public static bool AccountEnabled
{
get
{
return UserSettings.account_enabled;
}
set
{
UserSettings settings = UserSettings;
settings.account_enabled = value;
UserSettings = settings;
}
}
public static UserSettings UserSettings
{
get
{
if (userSetting == null)
{
if (File.Exists(UserSettingsFile))
{
userSetting = Serializer.XmlDeserializeObject<UserSettings>(UserSettingsFile);
}
else
{
userSetting = new UserSettings();
Serializer.XmlSerializeObject(userSetting, UserSettingsFile);
}
}
return userSetting;
}
set
{
if (value == null)
{
throw new ArgumentNullException("value is null!");
}
userSetting = value;
if (File.Exists(UserSettingsFile))
{
File.Delete(UserSettingsFile);
}
Serializer.XmlSerializeObject(userSetting, UserSettingsFile);
}
}
public static string UserSettingsFile
{
get
{
if (string.IsNullOrEmpty(pUserSettingsFile))
{
pUserSettingsFile = Path.Combine(GroupShootDroid.Singleton.ContentDirectory, "UserSettings.xml");
}
return pUserSettingsFile;
}
}
#endregion
}
public class UserSettings
{
public bool account_enabled { get; set; }
public string address { get; set; }
public string country { get; set; }
}
It's not rocket science, but does what I need it to do.
What I'm trying to do is use the Get/SetPropertyValue methods to return or set any of the properties within the class.
Currently, to access the Get/SetPropertyValue methods I'm using this
public string GetStringValue(string valToGet)
{
string rv = (string)UserData.GetPropertyValue(valToGet);
return rv;
}
public void SetStringValue(string name, string val)
{
UserData.SetPropertyValue(name, val);
}
On compiling though, the GetPropertyValue method is giving an error that No overload for method GetPropertyValue takes 1 argument with the SetPropertyValue complaining that there isn't an overload that takes 2
I'm not sure that the code I'm using will do what I need it to do (from what I've read on here it should be), but I'm more perplexed as to why the errors are showing.
Is there a better way to do what I'm trying to do? The application is a Xam.Forms app, so the PCL accesses the class through an interface using injection.
You are defining extension method, you need an instance of the class to call them:
var o = new Object();
string rv = (string)o.GetPropertyValue(valToGet);
// or, but no sure
string rv = (string)UserData.GetPropertyValue(o, valToGet);
or more probably in your case:
public string GetStringValue(string valToGet)
{
string rv = (string)this.GetPropertyValue(this, valToGet);
//or
//string rv = (string)UserData.GetPropertyValue(this, valToGet);
return rv;
}
I think you're getting confused between the UserData class and the object class. Your extension methods extend object.
EDIT: Question Reconstructed.
OK, I have revisited my get and set methods, but I am still very unclear on how it all works.
What I want to achieve is the Model is populated by the Controller, from the values that it takes form the form. This is then sent to the Db_Facade, which compares the uName and uPwd, and if they are equal returns the ACCESS, which will be set for the entire scope of the program.
I don't know if the get and set declarations are done correctly, or if they can be bunched together (If this is possible it would be great because I will be using this for much larger collections of data), and I'm pretty sure I'm implementing them wrong as well.
If you can help, my knowledge of Accessors is incredibly limited.
Here is my Compare Login method in my Controller:
public static void Compare_Login(User_Login_View Login_View)
{
User_Model getACCESS = new User_Model(); // Creates a new oject of User_Model
getACCESS.Name = Login_View.txtUsername.Text; //Populates the Model from the Login View
getACCESS.Pwd = Login_View.txtPassword.Text;
if (getACCESS.ACCESSLEVEL > 0)
{
Login_View.Close();
}
else
{
Login_View.lblError.Visible = true;
}
Login_View.Menu.SetMenuView();
}
Here is my Model:
public class User_Model
{
public string Name
{
get
{
return Db_Facade.uName;
}
set
{
Db_Facade.uName = value;
}
}
public string Pwd
{
get
{
return Db_Facade.uPwd;
}
set
{
Db_Facade.uPwd = value;
}
}
public int ACCESSLEVEL
{
get
{
return Db_Facade.ACCESS;
}
set
{
Db_Facade.ACCESS = value;
}
}
}
Here is the dummy database comparison:
class Db_Facade
{
public static string uName;
public static string uPwd;
public static string cPwd;
public static int ACCESS;
public static void getLoginACCESS()
{
uName = "paul";
uPwd = "pwd";
ACCESS = 1;
/* I get a "getACCESS does not exist" error here
if (uName == getACCESS.Name && uPwd == getACCESS.Pwd)
{
getACCESS.ACCESSLEVEL = ACCESS;
}
else
{
getACCESS.ACCESSLEVEL = 0;
}
*/
}
}
I don't know if it's needed, but here is my View
public partial class User_Login_View : Form
{
public Menu_View Menu { get; set; }
public User_Login_View()
{
InitializeComponent();
}
private void btnLogin_Click(object sender, EventArgs e)
{
User_Controller.Compare_Login(this);
}
}
2 Questions / Hints
1.) Where do you call your getLoginACCESS() ?
2.) Why do you think Db_Facade is able to access getACCESSfrom your class User_Controller?
a solution would be to modyfie your getLoginACCESS() to getLoginACCESS(User_Model getACCESS) and than call it in your Compare_Login(User_Login_View Login_View) befor your if like Db_Facade.etLoginACCESS(getACCESS);
I'm trying to send an object of a custom class through my asmx webservice running on .net 4.0, but all i get is an empty response. See below:
<soap:Body>
<ActivateResponse xmlns="http://tempuri.org/">
<ActivateResult /> <!-- why is this empty -->
</ActivateResponse>
</soap:Body>
However, if i modify my method and change the return type for example from class A to B, then it returns all the properties of object B correctly. See below:
<ActivateResponse xmlns="http://tempuri.org/">
<ActivateResult>
<BtAddress>string</BtAddress>
<Name>string</Name>
<Number>string</Number>
</ActivateResult>
</ActivateResponse>
I'm wondering why its happening? I could blame to improper Serialization of class A but there's nothing fancy I'm involving in my class files. Both class files are almost similar in terms of contents and does not contain any Serialize attribute.
So, why does the webservice return one type, but not the other?
Class A:
public class A
{
private string code;
private bool isValid;
private int maxUniqueActivations;
private DateTime dateAdded;
private Customer customer = null;
private bool _initAsEmpty = false;
public License()
{
_initAsEmpty = true;
}
public string LicenseCode
{
get { return code; }
//set { code = String.IsNullOrWhiteSpace(value)? null : value.Trim(); }
}
//If i change return type to Customer, it works too
//so i dont think it should be blamed
public Customer Customer
{
get { return customer; }
}
public bool IsValid
{
get { return isValid; }
}
public int MaxUniqueActivations
{
get { return maxUniqueActivations; }
}
public DateTime DateAdded
{
get { return dateAdded; }
}
}
Class B:
public class Phone
{
private string btAddress, name, number;
private bool isValid;
private DateTime dateAdded;
private bool _initAsEmtpy = false;
public Phone()
{
_initAsEmtpy = true;
}
public string BtAddress
{
get { return btAddress; }
set { btAddress = string.IsNullOrWhiteSpace(value) ? null : value.Replace(":", "").Trim(); }
}
public string Name
{
get { return name; }
set { name = string.IsNullOrWhiteSpace(value) ? null : value.Trim(); }
}
public string Number
{
get { return number; }
set { number = string.IsNullOrWhiteSpace(value) ? null : value.Trim(); }
}
public bool IsValid
{
get { return isValid; }
}
public DateTime DateAdded
{
get { return dateAdded; }
}
}
some methods are suppressed
In order to be serializable, a class must have public setters on its properties. That's the difference between classes A and B, and the reason why A won't serialize.
Probably :)
I think the problem may be with the Customer class. Maybe it is private or something. Try checking it out.
The Problem:
All tables in our database have CreatedDate, CreatedBy, ChangedDate, ChangedBy fields which I want to be set automatically when Saving / Updating an ActiveRecord entity.
My first try was to override the Save() and Update() methods. But these methods only get called when I do a direct Save() or Update() on the entity. They are not being called in a Master - Detail scenario where I call Save() only on the master.
Next try were the OnSave() and OnUpdate() methods, but here changes in the fields were not persisted in the database.
Finally I tried the BeforeSave() method. But this method is not called when updating.
The Question:
How can set these CreatedDate, CreatedBy, ChangedDate, ChangedBy fields automatically during a Save() or Update()?
To modify data as you you want you have to override the BeforeSave method like this:
protected override bool BeforeSave(IDictionary state)
{
bool retval = base.BeforeSave(state);
state["Password"] = Global.Encrypt("password");
return retval;
}
And finally save your instance:
protected void btnSave_Click(object sender, EventArgs e)
{
try
{
qfh.User user = null;
user = new qfh.User();
user.UserName = txtUserName.Text;
user.Name = txtName.Text;
user.IsAdministrator = cboIsAdministrador.SelectedValue == "Yes";
user.IsActive = cboIsActive.SelectedValue == "Yes";
user.SaveCopy();
}
catch (Exception ex)
{
ex = Utilities.GetInnerException(ex);
JSLiteral.Text = Utilities.GetFormattedExceptionMessage(ex);
}
}
I usually use SaveCopy() to make use of the overriden method FindDirty(object id, IDictionary previousState, IDictionary currentState, NHibernate.Type.IType[] types) to get the previous values of the class.
Hope it helps.
Use BeforeSave() for saving and OnFlushDirty() for updating.
you could do like this
[ActiveRecord("PostTable")]
public class Post : ActiveRecordBase<Post>
{
private int _id;
private DateTime _created;
[PrimaryKey]
public int Id
{
get { return _id; }
set { _id = value; }
}
[Property("created")]
public DateTime Created
{
get { return _created; }
set { _created = value; }
}
private void BeforeUpdate()
{
// code that run before update
Created = DateTime.Now;
}
public override void Update()
{
BeforeUpdate();
base.Update();
}
I had a same problem and solved it this way:
I use OnUpdate() and OnSave(). As you mentioned this solution does not work with master detail scenarios. For this I set parent of each child explicitly. Note following codes:
[ActiveRecord(Lazy = true)]
public class Lookup : ActiveRecordBase<Lookup>
{
[HasMany(typeof(LookupItem), Cascade = ManyRelationCascadeEnum.All)]
public virtual IList Items { set; get; }
//other properties...
}
[ActiveRecord(Lazy = true)]
public class LookupItem : ActiveRecordBase<LookupItem>
{
[BelongsTo("Lookup_id")]
public virtual Lookup ContainerLookup { set; get; }
//other properties...
}
void SaveLookup()
{
Lookup lookup = GetLookup();
LookupItem lookupItem = new LookupItem()
{
Title = LookupItemName,
ContainerLookup = lookup
};
lookup.Items.Add(lookupItem);
lookup.Save();
}