I have this class:
public class CompetitionBindingViewModel
{
[Required]
public string Name { get; set; }
public string Description { get; set; }
}
public class CompetitionViewModel : CompetitionBindingViewModel
{
public int Id { get; set; }
public string Logo { get; set; }
public string BackgroundImage { get; set; }
public string ColourScheme { get; set; }
public bool Current { get; set; }
public CompetitionViewModel(Competition model)
{
this.Id = model.Id;
this.Name = model.Name;
this.Description = model.Description;
this.Logo = model.Logo;
this.BackgroundImage = model.BackgroundImage;
this.ColourScheme = model.ColourScheme;
this.Current = model.Current;
}
}
As you can see there are 2 ViewModels here. One is for when a competition is first created (only the Name and Description need to be supplied. Later in the project I want to assign a Logo, BackgroundImage and ColourScheme, but these are not required.
I also have a Current value which by default is set to False.
I have this function which handles all that:
[Route("")]
public async Task<IHttpActionResult> Put(CompetitionViewModel model)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
try
{
var competition = await this.service.GetAsync(model.Id);
competition.Name = (string.IsNullOrEmpty(model.Name)) ? competition.Name : model.Name;
competition.Description = (string.IsNullOrEmpty(model.Description)) ? competition.Description : model.Description;
competition.Logo = (string.IsNullOrEmpty(model.Logo)) ? competition.Logo : model.Logo;
competition.BackgroundImage = (string.IsNullOrEmpty(model.BackgroundImage)) ? competition.BackgroundImage : model.BackgroundImage;
competition.ColourScheme = (string.IsNullOrEmpty(model.ColourScheme)) ? competition.ColourScheme : model.ColourScheme;
competition.Current = (model.Current == competition.Current) ? competition.Current : model.Current;
this.service.Update(competition);
}
catch (Exception ex)
{
return InternalServerError(ex);
}
return await base.SaveChanges();
}
Now, I like neat code and this just not do it for me. The lines that are an issue are these ones here:
competition.Name = (string.IsNullOrEmpty(model.Name)) ? competition.Name : model.Name;
competition.Description = (string.IsNullOrEmpty(model.Description)) ? competition.Description : model.Description;
competition.Logo = (string.IsNullOrEmpty(model.Logo)) ? competition.Logo : model.Logo;
competition.BackgroundImage = (string.IsNullOrEmpty(model.BackgroundImage)) ? competition.BackgroundImage : model.BackgroundImage;
competition.ColourScheme = (string.IsNullOrEmpty(model.ColourScheme)) ? competition.ColourScheme : model.ColourScheme;
competition.Current = (model.Current == competition.Current) ? competition.Current : model.Current;
What I am trying to do is check to see if a Property has changed. If it has, then take the new value otherwise leave it alone.
Can someone help me provide a better solution because this happens a lot (I have other classes and functions that do the same thing but with different properties).
I would prefer not to use a library as I don't like have libraries and using a tiny bit of it when it is there to address a multitude of situations.
Couldn't you just create a helper method or something? Not that it's pretty or has any error checking, but this works:
public static void UpdateValueIfChanged<TData,TValue>(TData data, Expression<Func<TData,TValue>> propFunc, TValue newValue)
{
var prop = (MemberExpression)propFunc.Body;
var propInfo = (PropertyInfo)prop.Member;
Func<TData, TValue> getFunc = propFunc.Compile();
TValue originalValue = getFunc(data);
if (!EqualityComparer<TValue>.Default.Equals(originalValue,newValue))
{
propInfo.SetMethod.Invoke(data, new object[] { newValue });
}
}
You can call it like UpdateIfChanged(competition c => c.Name, model.Name).
Related
There are few properties that need to be in sync and required null check before it's use. They are on different class.
What will be the better way to keep them in sync?
Example:
public class A
{
public string Name { get; set; }
public string VNumber { get; set; }
public string VLNumber { get; set; }
}
//Method One has below check:
if (new[] { A.Name, A.VNumber, A.VLNumber }
.Any(string.IsNullOrEmpty))
{
//Some error message;
}
//Somewhere else:
public class B
{
public string Name { get; set; }
public string VNumber { get; set; }
public string VLNumber { get; set; }
}
//Method Two has below check:
if (string.IsNullOrEmpty(B.Name))
{
return false;
}
if (string.IsNullOrEmpty(B.VNumber))
{
return false;
}
if (string.IsNullOrEmpty(B.VLNumber))
{
return false;
}
Since class A and class B has the same properties, they could be one (or at least inherit a common base class). The null check also seems to make use of the same logic, so it would be reasonable to put it in the base class too.
// Abstract base class (no instance of it can be made).
public abstract class BaseClass
{
public string Name { get; set; }
public string VNumber { get; set; }
public string VLNumber { get; set; }
// Logic for the common null checks.
// This logic will be used for all of BaseClass's sub classes.
public bool AnyPropertyIsNull()
{
return string.IsNullOrEmpty(Name)
|| string.IsNullOrEmpty(VNumber)
|| string.IsNullOrEmpty(VLNumber);
}
}
// Inherits base class
public class A : BaseClass
{ }
// Inherits base class
public class B : BaseClass
{ }
Example usage of the classes:
var b = new B();
bool bHasNullValues = b.AnyPropertyIsNull();
If you want a universal solution to check any class's public and string properties then you need to use reflections in c# (see Reflections in c#).
For this case you may use this method to check any class's string and public properties to null or empty:
public bool CheckAnyStringPublicPropertyIsNotEmpty(object obj)
{
var t = obj.GetType();
var properties = t.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(w => w.CanRead && w.CanWrite)
.Where(w => w.PropertyType == typeof(string))
.Where(w => w.GetGetMethod(true).IsPublic)
.Where(w => w.GetSetMethod(true).IsPublic);
foreach (var prop in properties)
{
var propValue =(t.GetProperty(prop.Name).GetValue(obj,null)??string.Empty).ToString();
if (string.IsNullOrEmpty(propValue))
return false;
}
return true;
}
and you may use something like this in your case:
var aObj = new A();
var result1 = CheckAnyStringPublicPropertyIsNotEmpty(aObj); //false
var bObj = new B(){Name="BName",VLNumber="2",VNumber="3"}
var result2 = CheckAnyStringPublicPropertyIsNotEmpty(bObj); //true
I'm new to Entity Framework. I was trying to get my data from my local database through this basic line of code, I wanted to store all of the objects in the "Object" row into a list.
But it seems like it doesn't work, whatever I try. I'm running SQL server, ASP.NET MVC. My code is something like these:
[HttpGet]
public List<Object> Function1()
{
List<Object> result = new List<Object>();
using (DatabaseContext db = new DatabaseContext())
{
result = db.Object.ToList();
// ...
return result;
}
}
It always ended up with "Specified cast is not valid." error:
This is where the error was caught:
Line 137: result = db.Object.ToList();
This is my model class, I added some functions though, but I haven't changed any default properties that Entity set up for me :
public partial class Object
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public int Like { get; set; }
public int View { get; set; }
public byte Level
{
get { return Level; }
set
{
if (value < 1 || value > 3)
{
Level = 1;
throw new Exception("Level must be in 1 to 3. By default, it becomes 1");
}
else
{
Level = value;
}
}
}
public string Introduction { get; set; }
public string VideoUrl { get; set; }
public string Tag { get; set; }
public string Steps { get; set; }
public DateTime Date { get; set; }
public Object(string name, byte level, string introduction = null)
{
this.Name = name;
this.Level = level;
this.Introduction = introduction;
}
}
Is it oke to add functions and fix the properties like that ??
This is my table design in sql : pic
You have used public byte Level auto-property with a custom setter method.
This should be accompanied with a private backing variable. Something like
private byte _level
public byte Level
{
get { return _level; }
set
{
if (value < 1 || value > 3)
{
_level = 1;
throw new Exception("Level must be in 1 to 3. By default, it becomes 1");
}
else
{
_level = value;
}
}
}
You need to case the Object into a specific Model object something like this
[HttpGet]
public List<Object> Function1()
{
List<Object> result = new List<Object>();
using (DatabaseContext db = new DatabaseContext())
{
//result = db.Object;
result = (from d in db.Object.ToList()
select new Object{
prop1 = d.prop1,
prop2 = d.prop2,
.......
}).ToList();
// ...
return result;
}
}
I have following class:
public class ContentVideoType
{
public string Title { get; set; }
public string GetThumbnail { get; set; }
}
When creating an instance of this class, I want to assign a custom getter for GetThumbnail. I don't know how it is called but as far as I know the code must be like:
var youtube = new ContentVideoType
{
Title = "Youtube",
GetThumbnail = (x) => { return $"https://i.ytimg.com/vi/{x}/mqdefault.jpg"; }
};
var vimeo = new ContentVideoType
{
Title = "Vimeo",
GetThumbnail = (x) => GetVimeoImage(x)
};
For Viemo for example I need to call following function for GetThumbnail:
public static string GetVimeoImage(string vimeoId)
{
string result = String.Empty;
try
{
XmlDocument doc = new XmlDocument();
doc.Load("http://vimeo.com/api/v2/video/" + vimeoId + ".xml");
XmlElement root = doc.DocumentElement;
result = root.FirstChild.SelectSingleNode("thumbnail_medium").ChildNodes[0].Value;
}
catch
{
//cat with cheese on it's face fail
}
return result;
}
I suppose, that you want to achieve inheritance in some odd way :) You should really use proper inheritance here (GetThumbnail should be method if it is receiving a string as a parameter):
public abstract class ContentVideoType
{
public virtual string Title { get; set; }
public virtual string GetThumbnail(string id)
{
return "Some Default Thumbnail";
}
}
public class YouTubeContentVideType : ContentVideoType
{
public override string GetThumbnail(string id)
{
return "";//your logic for youTube
}
}
public class VimeoContentVideType : ContentVideoType
{
public override string GetThumbnail(string id)
{
return "";//your logic for vimeo
}
}
=== UPDATE ===
Basing on your latest response - here is how it would look :
void Main()
{
foreach (var videoType in GetAll)
{
Console.WriteLine(videoType.Title + " " + videoType.GetThumbnail("1")));
}
}
public abstract class ContentVideoType
{
public virtual string Title { get; }
public virtual string GetThumbnail(string id)
{
return "Some Default Thumbnail";
}
}
public class YouTubeContentVideoType : ContentVideoType
{
public override string Title { get; } = "Youtube";
public override string GetThumbnail(string id)
{
return $"https://i.ytimg.com/vi/{id}/mqdefault.jpg";
}
}
public class VimeoContentVideType : ContentVideoType
{
public override string Title { get; } = "Vimeo";
public override string GetThumbnail(string id)
{
return GetVimeoPreview(id);
}
public string GetVimeoPreview(string videoId)
{
return $"url:{videoId}"; //your code here;
}
}
public static List<ContentVideoType> GetAll
{
get
{
var result = new List<ContentVideoType>
{
new YouTubeContentVideoType(),
new VimeoContentVideType()
};
return result;
}
}
It sounds like you want GetThumbnail to be a method that returns a string, not just a string. You can re-declare this way in order to do that:
public Func<string, string> GetThumbnail { get; set; }
That would cause this code to compile:
var youtube = new ContentVideoType
{
Title = "Youtube",
GetThumbnail = (x) => {
return string.Format("https://i.ytimg.com/vi/{0}/mqdefault.jpg", x); }
};
Note that the GetThumbnail above only accepts a method that takes one argument and returns a string.
Edit: Here's an example of how to use this:
string thumbnail = youtube.GetThumbnail("abc");
Could you create two sub-classes to ContentVideoType and each one implementing their own version of GetThumbnail?
Otherwise, the fact of being able to swap getters with reflection seems impossible: https://stackoverflow.com/a/6835824/2525304
Ok, here is how I did it with a little help and guessing :)
public class ContentVideoType
{
public string Title { get; set; }
public Func<string, string> GetThumbnail { get; set; }
}
public static List<ContentVideoType> GetAll
{
get
{
var result = new List<ContentVideoType> {
new ContentVideoType
{
Title = "Youtube",
GetThumbnail = videoId => $"https://i.ytimg.com/vi/{videoId}/mqdefault.jpg"
},
new ContentVideoType
{
Title = "Vimeo",
GetThumbnail = videoId => GetVimeoPreview(videoId)
}
};
return result;
}
}
How can I access the custom attribute of the parent or owner object.
Look at the FieldInfo property of the SQLFieldInfo struct
Here's a more detailed program that will compile and run that shows what I need.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Employee myclass = new Employee();
// Load from sql server...
myclass.Name = "Alain";
myclass.Age = 51;
//----
MessageBox.Show(myclass.Name.ToString()); // Should return Alain
MessageBox.Show(myclass.Age.FieldInfo.Type.ToString()); // Should output "int"
}
}
// This next class is generated by a helper exe that reads SQL table design and create the class from it
[SQLTableAttribute(DatabaseName = "Employees", Schema = "dbo", TableName = "Employees")]
public class Employee
{
[SQLFieldAttribute(FieldName = "ID", Type = SqlDbType.Int)]
public SQLFieldInfo<int> ID { get; set; }
[SQLFieldAttribute(FieldName = "Name", Type = SqlDbType.NVarChar, Size = 200)]
public SQLFieldInfo<String> Name { get; set; }
[SQLFieldAttribute(FieldName = "Age", Type = SqlDbType.Int)]
public SQLFieldInfo<int> Age { get; set; }
}
public struct SQLFieldInfo<T>
{
private readonly T value;
public SQLFieldInfo(T Value)
{
this.value = Value;
}
public static implicit operator SQLFieldInfo<T>(T Value)
{
return new SQLFieldInfo<T>(Value);
}
public T Value
{
get
{
return this.value;
}
}
public override string ToString()
{
return this.value.ToString();
}
public SQLFieldAttribute FieldInfo
{
get
{
// Need to retreive the attribute class of the parent or declaring member
return null;
}
}
}
// Holds the sql field information
public class SQLFieldAttribute : Attribute
{
public string FieldName { get; set; }
public SqlDbType Type { get; set; }
public bool AllowNull { get; set; }
public int Size { get; set; }
}
// Holds the sql table information
public class SQLTableAttribute : Attribute
{
public string DatabaseName { get; set; }
public string Schema { get; set; } = "dbo";
public string TableName { get; set; }
}
Thank you!
Alain
My data class is as follows (should be fairly translatable to A above):
public class Foo
{
[Argument(Help = "Name", AssignmentDelimiter = "=")]
public string Name
{
get;
set;
}
}
A helper class is responsible of reading attribute values of objects:
static public string GetCommandLineDelimiter<T>(Expression<Func<T>> property)
{
if(property != null)
{
var memberExpression = (MemberExpression)property.Body;
string propertyName = memberExpression.Member.Name;
PropertyInfo prop = typeof(Arguments).GetProperty(propertyName);
if(prop != null)
{
object[] dbFieldAtts = prop.GetCustomAttributes(typeof(ArgumentAttribute), true);
if(dbFieldAtts.Length > 0)
{
return ((ArgumentAttribute)dbFieldAtts[0]).AssignmentDelimiter;
}
}
}
return null;
}
To use it, simply:
string delimiter = GetCommandLineDelimiter(() => myObject.Name);
That will get the attribute value of AssignmentDelimiter on property Name, i.e. "=".
First, MSDN is your friend.
Then, if you want to get the attributes for ancestors just specify true in the inherit flag of the method:
var attribute = typeof(A).GetProperty("myprop").GetCustomAttributes(true)
.OfType<MycustomAttrib>().FirstOrDefault();
This works. I am doing a lazy initialization of a reference to the custom attribute by using reflection to look at all the properties of all the types.
public class MycustomAttribAttribute : Attribute
{
public MycustomAttribAttribute(string name)
{
this.Name=name;
}
public string Name { get; private set; }
}
class A
{
public A() { MyProp=new B(); }
[MycustomAttrib(name: "OK")]
public B MyProp { get; set; }
}
class B
{
private static Lazy<MycustomAttribAttribute> att = new Lazy<MycustomAttribAttribute>(() =>
{
var types = System.Reflection.Assembly.GetExecutingAssembly().DefinedTypes;
foreach(var item in types)
{
foreach(var prop in item.DeclaredProperties)
{
var attr = prop.GetCustomAttributes(typeof(MycustomAttribAttribute), false);
if(attr.Length>0)
{
return attr[0] as MycustomAttribAttribute;
}
}
}
return null;
});
public string MyProp2
{
get
{
return att.Value.Name;
}
}
}
class Program
{
static void Main(string[] args)
{
// Finds the attribute reference and returns "OK"
string name = (new A()).MyProp.MyProp2;
// Uses the stored attribute reference to return "OK"
string name2 = (new A()).MyProp.MyProp2;
}
}
I'm creating a view model for a Customer entity in EF. My question is if I'm using the correct approach. I convert an entity property to a view model property. And, if what I need to return is a list I convert the properties for each object.
Is there a better way to do this serialization? I'm not asking about if convert an entity to a model is the correct approach. I'm not doing that, I just return what is needed. What I want to know is if is there a better way to serialize the entity to an object in a view model.
This is my view model:
public class CustomerModel
{
public int TotalRecords { get; set; }
public int CUSTOMER_KEY { get; set; }
public decimal CCUSTID { get; set; }
public string CCNAME { get; set; }
public string ACCNOTES { get; set; }
public string CUSTPRCLEVEL_CODE { get; set; }
public string CUSTPRCLEVEL_CODE_Name { get; set; }
public DateTime LASTMODIFIEDDATE { get; set; }
public string LASTMODIFIEDBY { get; set; }
public static Customer FromModelToEntity(CustomerModel model)
{
Customer entity = new Customer();
entity.CUSTOMER_KEY = model.CUSTOMER_KEY;
entity.CCUSTID = model.CCUSTID;
entity.CCNAME = model.CCNAME != null ? model.CCNAME : null;
entity.ACCNOTES = model.ACCNOTES != null ? model.ACCNOTES : null;
entity.CUSTPRCLEVEL_CODE = model.CUSTPRCLEVEL_CODE != null ? model.CUSTPRCLEVEL_CODE : null;
entity.LASTMODIFIEDDATE = model.LASTMODIFIEDDATE;
entity.LASTMODIFIEDBY = model.LASTMODIFIEDBY != null ? model.LASTMODIFIEDBY : null;
return entity;
}
public static CustomerModel FromEntityToModel(Customer entity)
{
CustomerModel model = new CustomerModel();
model.CUSTOMER_KEY = entity.CUSTOMER_KEY;
model.CCUSTID = entity.CCUSTID;
model.CCNAME = entity.CCNAME != null ? entity.CCNAME : null;
model.ACCNOTES = entity.ACCNOTES != null ? entity.ACCNOTES : null;
model.CUSTPRCLEVEL_CODE = entity.CUSTPRCLEVEL_CODE != null ? entity.CUSTPRCLEVEL_CODE : null;
model.CUSTPRCLEVEL_CODE_Name = entity.CustomerPricingLevel != null ? entity.CustomerPricingLevel.DESCRIPTION : string.Empty;
model.LASTMODIFIEDDATE = entity.LASTMODIFIEDDATE;
model.LASTMODIFIEDBY = entity.LASTMODIFIEDBY != null ? entity.LASTMODIFIEDBY : null;
return model;
}
public static List<Customer> FromModelToEntity(List<CustomerModel> modelList)
{
List<Customer> entityList = new List<Customer>();
foreach (var item in modelList)
{
entityList.Add(CustomerModel.FromModelToEntity(item));
}
return entityList;
}
public static List<CustomerModel> FromEntityToModel(List<Customer> entityList)
{
List<CustomerModel> modelList = new List<CustomerModel>();
foreach (var item in entityList)
{
modelList.Add(CustomerModel.FromEntityToModel(item));
}
return modelList;
}
}
Not sure what sort of answer you are seeking.
You can shorten your code using LINQ though. (System.Linq)
Insead of the foreach, you can use a 1 liner:
So that this:
public static List<Customer> FromModelToEntity(List<CustomerModel> modelList)
{
List<Customer> entityList = new List<Customer>();
foreach (var item in modelList)
{
entityList.Add(CustomerModel.FromModelToEntity(item));
}
return entityList;
}
Turns into this:
public static List<Customer> FromModelToEntity(List<CustomerModel> modelList)
{
return modelList.Select(item => FromModelToEntity(item)).ToList();
}