I have three columns in the db table that looks as follow:
When I add a new row, it should store the value on column fieldname in uppercase. How can I do that?
Since you tagged the question with entity framework, I assume you want to do it in your data layer or close to DB. There's a number of ways for doing this.
You could override SaveChanges() in your context. This will move the logic away from the model, but still ensure that the correct value is saved. Also, if you want it on several entities you can use an interface. When it's an interface you can do it for several of your entities without any duplicate code, as long as it's the same property. Otherwise you would need an attribute and reflection. Reusability is pretty high, but it adds some overhead to your SaveChanges().
public class CustomerEntity()
{
public string Name {get;set;}
}
public MyCustomContext : DbContext
{
// Other stuff...
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries<CustomerEntity>())
{
if (entry.State == EntityState.Modified || entry.State == EntityState.Added)
{
// Possibly check for null or if it's changed at all.
entry.Entity.Name = entry.Entity.Name.ToUpper();
}
}
return base.SaveChanges();
}
}
And with an interface:
public interface INameIsAlwaysUpperCase
{
string Name {get;set;}
}
public MyCustomContext : DbContext
{
// Other stuff...
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries<INameIsAlwaysUpperCase>())
{
if (entry.State == EntityState.Modified || entry.State == EntityState.Added)
{
// Possibly check for null or if it's changed at all.
entry.Entity.Name = entry.Entity.Name.ToUpper();
}
}
return base.SaveChanges();
}
}
You can add a custom validation. This will throw exception if it's not saved correctly. That way you can move the responsibility to the consumer of the model. However, depending on your scenario, you might not want to throw an exception. This is my favourite since it forces the consumer to do it the right way. As per comments, why throw when you can silently convert it? Yes, it's a valid question. For me it's about forcing the consumer of the data layer to use it correctly, and not let the daya layer decide what to to with the data. I personally don't like it when the business layer asks the data layer to save one thing, and then the data layer saves another thing. If lower case isn't a valid option, then it shouldn't be saved. I don't think it's much more different from using [Required]. But it's really about context and what works in your particular case.
public class CustomerEntity() : IValidatableObject
{
public string Name {get;set;}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
// Possibly check for null here as well...
if (this.Name.ToUpper() != this.Name)
{
yield return new ValidationResult("You need to save as upper!");
}
}
}
Use a property that manages this for you. This may be the simplest solution, even if I like to keep my entities "clean". It's absolutely the solution that will require least effort. However, the reusability is low, and what if you use your entitites all over the application and want the value to be lower case until it's actually saved? That's not possible. But, again, I think it comes down to your particular situation. If you want the value to be upper case even before you save it, this is probably the best solution!
public class CustomerEntity()
{
string _name;
public string Name
{
get { return _name; }
set { _name = value.ToUpper(); } // Check for null ?
}
}
Do it when saving. This moves the logic to when you're saving your entity. This is probably the least preferable option, since the reusability is non-existing. What happens in Update()? However, the OP specifically states "When I add a new row", so it may only be applicable when adding new entities. And in that case it could very well be the most prefered choice since it allows updates to have lower case. But it would have to depend on the use case.
public void AddCustomer(string name)
{
var customer = new CustomerEntity
{
Name = name.ToUpper()
};
_context.Customers.Add(customer);
}
Just use properties. If your model is as below:
public class MyModel
{
public int Id { get; set; }
public string Description { get; set; }
public string LanguageCode { get; set; }
public string FiledName { get; set; }
}
Then, change it to:
public class MyModel
{
private string fieldName;
public int Id { get; set; }
public string Description { get; set; }
public string LanguageCode { get; set; }
public string FiledName
{
get { return filedName; }
set
{
if(!string.IsNullOrEmpty(value))
fieldName = value.ToUpper();
else
fieldName = value;
}
}
}
Try this.
public string FiledName
{
get { return filedName; }
set
{
filedName = !string.IsNullOrEmpty( value ) ? value.ToUpper() : value;
}
}
Using a ValueConverter on the Property could be an effective way to do this.
public class YourDbContext : DbContext
{
public YourDbContext(DbContextOptions<YourDbContext> options)
: base(options)
{
}
public DbSet<Row> Rows { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
var converter = new ValueConverter<string, string>(
v => v.ToUpper(), // writing
v => v
);
// just one property
modelBuilder.Entity<Row>()
.Property(x => x.Column)
.HasConversion(converter);
// all of the string properties
foreach (var entityType in builder.Model.GetEntityTypes())
{
foreach (var property in entityType.GetProperties())
{
if (property.ClrType == typeof(string))
{
builder.Entity(entityType.Name)
.Property(property.Name)
.HasConversion(converter);
}
}
}
}
}
It's also possible to use a Custom Attribute :
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class Standardized : Attribute
{}
Then decorate properties inside your model :
public class MyModel
{
public string Id{ get; set; }
[Required]
[Standardized]
public string Description { get; set; }
}
Taken from #smoksnes accepted answer, inside your DbContext class, override SaveChanges(), SaveChangesAsync() (EF Core 5.x) and add a private method using reflection to obtain decorated properties and apply transformations, like this :
public override int SaveChanges()
{
StandardizeBeforeSaving();
return base.SaveChanges();
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
StandardizeBeforeSaving();
return await base.SaveChangesAsync(cancellationToken);
}
private void StandardizeBeforeSaving()
{
foreach (var entry in ChangeTracker.Entries())
{
if (entry.State == EntityState.Modified || entry.State == EntityState.Added)
{
var properties = entry.Entity
.GetType()
.GetProperties()
.Where(prop => Attribute.IsDefined(prop, typeof(Standardized)) && prop.PropertyType == typeof(string));
foreach (var property in properties)
{
var value = entry.CurrentValues[property.Name]?.ToString() ?? string.Empty;
entry.CurrentValues[property.Name] = value.Standardize();
}
}
}
}
Just be aware that reflection could be slower than other techniques presented in accepted answer. But for most scenarios (ie. user updates or creates couple of entities with not that many properties) it should be fine.
Related
I have fields for audit trail in each table (InsertedBy, InsertedDate, UpdatedBy and UpdatedDate), I build solution to reduce redundant before by override savechange():
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries().Where(e =>
e.State == System.Data.Entity.EntityState.Added || e.State == System.Data.Entity.EntityState.Modified))
{
Auditing.ApplyAudit(entry, User);
}
return base.SaveChanges();
}
public class Auditing
{
public static void ApplyAudit(DbEntityEntry entityEntry, int User)
{
Type type = entityEntry.Entity.GetType();
if (entityEntry.State.ToString() == "Added")
{
if (type.GetProperty("InsertedBy") != null)
{
entityEntry.Property("InsertedBy").CurrentValue = User;
}
if (type.GetProperty("InsertedDate") != null)
{
entityEntry.Property("InsertedDate").CurrentValue = DateTime.Now;
}
}
else if (entityEntry.State.ToString() == "Modified")
{
if (type.GetProperty("InsertedBy") != null)
{
entityEntry.Property("InsertedBy").IsModified = false;
}
if (type.GetProperty("InsertedDate") != null)
{
entityEntry.Property("InsertedDate").IsModified = false;
}
if (type.GetProperty("UpdatedBy") != null)
{
entityEntry.Property("UpdatedBy").CurrentValue = User;
}
if (type.GetProperty("UpdatedDate") != null)
{
entityEntry.Property("UpdatedDate").CurrentValue = DateTime.Now;
}
}
}
}
the question is:
is using reflection within each entity before modified or added waste in memory and performance ? if yes is there is best practice for this ?
is this another code snippet better in performance or just use reflection also?
public static void ApplyAudit(DbEntityEntry entityEntry, long User)
{
if (entityEntry.State.ToString() == "Added")
{
entityEntry.Property("InsertedBy").CurrentValue = User;
entityEntry.Property("InsertedDate").CurrentValue = DateTime.Now;
}
else if (entityEntry.State.ToString() == "Modified")
{
entityEntry.Property("InsertedBy").IsModified = false;
entityEntry.Property("InsertedDate").IsModified = false;
entityEntry.Property("UpdatedBy").CurrentValue = User;
entityEntry.Property("UpdatedDate").CurrentValue = DateTime.Now;
}
}
is entityEntry.Property("InsertedBy") uses reflection ?
Reflection is slow (slow is subjective) and if you want to avoid it, then you need to get rid of such code as below:
Type type = entityEntry.Entity.GetType();
if (type.GetProperty("InsertedBy") != null)
Even if it was not slow, the code above is still "buggy" because a programmer may mistakenly write InsertBy instead of InsertedBy. This can easily be avoided with help from the compiler using the approach below.
Use an interface and implement it in all entities that require audit.
public interface IAuditable
{
string InsertedBy { get; set; }
// ... other properties
}
public class SomeEntity : IAuditable
{
public string InsertedBy { get; set; }
}
public class Auditor<TAuditable> where TAuditable : IAuditable
{
public void ApplyAudit(TAuditable entity, int userId)
{
// No reflection and you get compiler support
if (entity.InsertedBy == null)
{
// whatever
}
else
{
// whatever
}
}
}
As mentioned in the comments, you will get compiler support and reflection is not used anymore. I would even go a step further and not pass the int userId. I will bring the code for figuring out the userId and put it in this class. That way the class is self sufficient and clients do not need to provide it this information.
Usage:
var e = new SomeEntity();
var auditor = new Auditor<SomeEntity>();
auditor.ApplyAudit(e, 1); // 1 is userId, I am just hardcoding for brevity
Or use it from your context:
public override int SaveChanges()
{
var auditables = ChangeTracker.Entries().Where(e =>
e.State == System.Data.Entity.EntityState.Added || e.State == System.Data.Entity.EntityState.Modified)
.OfType<IAuditable>();
var auditor = new Auditor<IAuditable>();
foreach (var entry in auditables)
{
// 1 is userId, I am just hardcoding for brevity
auditor.ApplyAudit(entry, 1);
}
return base.SaveChanges();
}
This means that all entities who are auditable will need to implement the IAuditable interface. EF generates partial classes for your entities but do not modify those partial classes because the next time you run the custom tool, it will be wiped out.
Instead, create another partial class with the same name and implement the IAuditable.
public partial class SomeEntity : IAuditable {}
An even better approach is to create a custom T4 template so it creates the partial class with the code : IAuditable. Please see this article for how to do that.
I am not sure that this title is correct..Anyways I have a class that has a number of methods that control a stereo. Each method will send a command to a serial port. There are many models of stereos supported and each stereo may have a different command that needs to be sent.
For example model_A may need to send the command "VOLUP" to the serial port and "model_B" may need to send the command "GAINUP" to increase the volume. I want to have one method called IncreaseVolume like this:
public void IncreaseVolume()
{
serialPort.WriteLine(volumeCommand);
}
This method will be called from another class after setting the model of the radio. Now for two radios I could do this:
public class StereoControl
{
string volumeCommand;
string model_A_Volume_Command = "VOLUP";
string model_B_VOlume_Command = "GAINUP";
public void Set_Radio_Model(string model)
{
if (model == "modelA")
{
volumeCommand = model_A_Volume_Command;
}
else if (model == "modelB")
{
volumeCommand = model_B_Volume_Command;
}
}
public void IncreaseVolume(volumeCommand)
{
serialPort.WriteLine(volumeCommand);
}
}
So the main program will first set the model and then anytime the volume needs increasing it will just call the IncreaseVolume method.
The things is that there are potentially dozens of stereos and dozens of commands and I don't necessarily want all these in if then or case statements.
I thought of creating structures for each model containing the commands but then how do you select which structure to use in the methods?
I am sure there is a more elegant way to do this and am open to suggestions.
The first answer while usable, when we get 100+ commands and 200+ stereo's it will be a bit too difficult to handle. So here is another possibility but I do not know how to get the class reference available throughout the application.
public Class Model_A
{
string volumeCommand = "VOLUP";
}
public Class Model_B
{
string volumeCommand = "GAINUP";
}
public Class StereoControl
{
public void Set_Radio_Model(String model)
{
if (model == "model_a")
{
var _radio = new Model_A();
}
else if (model == "model_b")
{
var _radio = new Model_B();
}
}
public void IncreaseVolume()
{
serialPort.WriteLine(_radio.volumeCommand);
}
}
Of course the issue here is that the scope of _radio is only within the Set_Radio_Model. Is there a way to _radio usable everywhere?
Tom
The very basic way is to have Enum of stereos names and then implement it in OOP
(I hope people help to improve it) this is just depends on my opinion.
1- Define enum like:
public enum StereoBrand
{
Stero1 = 0,
Stereo2 = 1
}
2- Define an interface to enforce all stereos implement IncreaseVolume() like:
public interface IStereo
{
string VolumeCommand { get; }
string SteroeName { get; }
void IncreaseVolume();
}
by above interface each stereo should have a name as StereoName.
3- And then implement StereoController like :
public class SteroController : IStereo
{
public virtual string SteroeName
{
get
{
return string.Empty;
}
}
public virtual string VolumeCommand
{
get
{
return string.Empty;
}
}
public virtual void IncreaseVolume()
{
throw new NotImplementedException();
}
public static SteroController GenerateStereo(StereoBrand brand)
{
SteroController stereo = null;
switch (brand)
{
case StereoBrand.Stero1:
stereo = new Stereo1();
break;
case StereoBrand.Stereo2:
stereo = new Stereo2();
break;
}
return stereo;
}
}
Notes of Step3:
3.1- StereoController implement IStereo and change that prop and Increase method to Virtual that all Stereo can override them.
3.2- GenerateStereo which create related stereo by its StereoName
4- Suppose we have to implement Stereo classes here Stereo1 and Stereo2 like:
public class Stereo1 : SteroController
{
public override string SteroeName
{
get
{
return "Streo1";
}
}
public override string VolumeCommand
{
get
{
return "Command1";
}
}
public override void IncreaseVolume()
{
//Do anything with VolumCommand
}
public Stereo1()
{
}
}
public class Stereo2 : SteroController
{
public override string SteroeName
{
get
{
return "Streo2";
}
}
public override string VolumeCommand
{
get
{
return "Command2";
}
}
public override void IncreaseVolume()
{
//Do anything with VolumCommand2
}
public Stereo2()
{
}
}
5- The last step is using them like:
var stero = SteroController.GenerateStereo((StereoBrand)Enum.Parse(typeof(StereoBrand), "brandName"));
stero.IncreaseVolume();
Notes:
N1: This is better to implement GenerateStereo by reflection which means find all IStereo and make an instance by reflection.
N2: The another solution to avoid switch-case is using reflection to find related Stereo like:
public static SteroController GenerateStereo(StereoBrand brand)
{
SteroController stereo = null;
var type = typeof(IStereo);
var types = AppDomain.CurrentDomain.GetAssemblies()//Find all classes which implemented ISereo
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p)).ToList();
foreach(Type t in types)
{
var stereoNameProp = t.GetProperties().SingleOrDefault(p => p.Name == "StereoName");//Get stereo name prop
if (stereoNameProp != null && stereoNameProp.GetValue(t).ToString() == brand.ToString())//Check it with brand name
stereo =(SteroController)Activator.CreateInstance(type);//Make an instance
}
return stereo;
}
Hope it help and give you the clue.
After reading similar issues I still did not managed to overcome this problem. What is interesting is that I decoupled and made a separate project and there it works.
I have two entities JobAnnouncement and Skill and they are in a many-to-many relationship. I am able to insert as long as I do not have any Skills added to the job announcement.
Let me put in the code:
public class JobAnnouncement
{
public int Id { get; set; }
public DateTime DateAdded { get; set; }
//other properties
public virtual ICollection<Skill> Skills { get; set; }
}
public class Skill
{
//other properties
public virtual ICollection<JobAnnouncement> JobAnnouncements { get; set; }
}
The insertion code is (tried all ways including the dumb ones):
public void AddJobAnnouncement(JobAnnouncement jobAnnouncemnet)
{
_jobAnnouncement.Content = jobAnnouncemnet.Content; //ok
_jobAnnouncement.CompanyId = jobAnnouncemnet.CompanyId; //ok
_jobAnnouncement.Skills = jobAnnouncemnet.Skills; //fails
db.JobAnnouncements.Add(_jobAnnouncement); //throws exception
db.SaveChanges();
}
Just for your information I did override the SaveChanges() method (that is why I left the DateAdded. I don't think that's causing the error, I tryied removin it and it still doesn't work.)
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries().Where(entry => entry.Entity.GetType().GetProperty("DateAdded") != null))
{
if (entry.State == EntityState.Added)
{
entry.Property("DateAdded").CurrentValue = DateTime.Now;
}
if (entry.State == EntityState.Modified)
{
entry.Property("DateAdded").IsModified = false;
}
}
}
}
Also, I am using Niject, and the instruction found on SO does not help:
kernel.Bind<CareerTrackContext>().To<CareerTrackContext>().InRequestScope();
I've even tried to alter the entity lifespan. The version of Entity Framework is 6.1.3 and I am using code first.
I just don't see the issue. What can I try next?
I found a fix ... not necessarily a solution. The AddJobAnnouncement should look like this:
public void AddJobAnnouncement(JobAnnouncement jobAnnouncemnet)
{
_jobAnnouncement.Content = jobAnnouncemnet.Content; //ok
_jobAnnouncement.CompanyId = jobAnnouncemnet.CompanyId; //ok
// it will by ok now
jobAnnouncement.Skills = new List<Skill>();
foreach (var skill in jobAnnouncemnet.Skills)
{
_jobAnnouncement.Skills.Add(db.Skills.Find(skill.Id));
}
}
Right now I don't even now why it works.
This may be trivial. But I could not able to get my heads over this.
public class Manager
{
public int ID { get; set; }
public List<Employee> Employees { get; set; }
public bool IsAllEmpEngaged { get; set; }
public void UpdateIsAllEmpEngaged()
{
IsAllEmpEngaged = Employees.All(emp => emp.IsEngagedwithWork == true);
}
}
public class Employee
{
public int ID { get; set; }
public bool IsEngagedwithWork { get; set; }
}
So, Whenever, the IsEngagedwithWork of Employee is setted with some value, I want to check whether all the Employees under aManager is Engaged with work or not and update the value of IsAllEmpEngaged of the respective Manager.
I just want to call UpdateIsAllEmpEngaged on changes in property IsEngagedwithWork of Employee. How can I achieve this?
Any other ways are also welcome.
Note: I tried with a having an event on Employee and attach Action from the Manager that will callback if any changes in Employee property. But I will be having hundreds of List<Manager>. I dont want to add event for each and every instance of Employee class. Any easy way?
Update:
I am working with WPF MVVM approach, I cannot use direct get with LinQ as it will not notify the UI. I have to set the property manually for change so that it will Notify the UI.
Also, In actual case, the IsEngagedwithWork will be updated in UI for the property IsEngagedwithWork.
Simple solution is add ManagerId as well to the Employee model class and after your line of code that sets IsEngagedwithWork of the employee instance (say emp), do the below thing
Manager mngr = managers.Select(m => m.ID == emp.ManagerId).FirstOrDefault();
if(mngr != null)
mngr.IsAllEmpEngaged = mngr.IsAllEmpEngaged && emp.IsEngagedwithWork;
I'd use the getter of the property like that
public bool IsAllEmpEngaged {
get {
return (Employees != null) &&
Employees.All(e => e.IsEngagedwithWork)
}
}
and you add the following method for the Manager Class
public void NotifyChanged() { OnPropertyChanged(() => IsAllEmpEngaged }
then you call it from the Employee Class (assuming you have the managers' list or an equivalent way)
private int _ID;
private bool _IsEngagedwithWork;
public int ID {
get { return _ID};
set {
_ID = value;
OnPropertyChanged(()=>ID );
notifyMe = managerList.FirstOrDefualt(m => m.ID == _ID);
if (notifyMe != null) { notifyMe.NotifyChanged()}
}
}
public bool IsEngagedwithWork {
get { return _IsEngagedwithWork ;}
set {
_IsEngagedwithWork = value;
OnPropertyChanged(()=>IsEngagedwithWork );
notifyMe = managerList.FirstOrDefualt(m => m.ID == _ID);
if (notifyMe != null) { notifyMe.NotifyChanged()}
}
}
What i would do :
make IsAllEmpEngaged private
make the collection Empoyess private and add a function that add a new employee:
Add a function that adds a new employee.
And now two choiches :
1) after the employee is added, iterate the collection and update the IsAllEmpEngaged property
public void AddNewEmployee(Employee employee){
this.Employees.Add(employee);
bool all = true;
foreach(Employee emp in this.Employees){
if (!emp.IsEngagedwithWork){
all = false;
break;
}
}
this.IsAllEmpEngaged = all;
}
2)
start with IsAllEmpEngaged = true; when the class is inited and the collection is empty
when the employee is added, update the IsAllEmpEngaged property but keeping count of the last choice (this works only if you don't remove employess)
public void AddNewEmployee(Employee employee){
this.Employees.Add(employee);
this.IsAllEmpEngaged = this.IsAllEmpEngaged && employee.IsEngagedwithWork
}
I can't say that this is any better, but surely this is a simple and easy way.
Why not just make IsAllEmpEngaged a method? You don't even need the set property accessor, so a method should suffice.
public bool IsAllEmpEngaged()
{
if (Employees == null)
{
// throw error
}
return Employees.All(e => e.IsEngagedwithWork);
}
Maybe it work's when you pass your Manager as parameter to Employee and then call your Method if IsEngagedWithWork is set to true.
public class Employee
{
private Manager _parentManager;
public Employee(Manager parentManager)
{
_parentManager=parentManager;
}
public int ID { get; set; }
private bool _isEngangedWithWork;
public bool IsEngagedwithWork
{
get{ return _isEngangedWithWork; }
set
{
_isEngangedWithWork=value;
if(_isEngangedWithWork)
_parentManager.UpdateIsAllEmpEngaged();
}
}
}
I have class which have too many related calculated properties.
I have currently kept all properties are read only.
some properties need long calculation and it is called again when its related properties are needed.
How can create this complex object .Also i want these properties should not be set from external code. I need show hide as i am binding properties for UI. Also i think order is also important.
My Class is something like
public string A
{
get
{
return complexMethod();
;
}
}
public string B
{
get
{
if (A == "value")
return "A";
else return "B";
;
}
}
public bool ShowHideA
{
get
{
return string.IsNullOrEmpty(A);
;
}
}
public bool ShowHideB
{
get
{
return string.IsNullOrEmpty(B);
;
}
}
public string complexMethod()
{
string value = "";
// calculation goes here
return value;
}
}
Thanks
You need to use Lazy type provided by .net:
Lazy<YourType> lazy = new Lazy<YourType>();
Make your properties internal to not be set from external code.
Well tall order isn't it?
One of the coolest things about extension methods is you can use types. This is perfect for writing external programs to calculate property values. Start like this...
public static class XMLibrary
{
public static MC CalculateValues(this MC myclass)
{
//for each property calculate the values here
if (myclass.Name == string.Empty) myclass.Name = "You must supply a name";
if (myclass.Next == 0) myclass.Next = 1;
//when done return the type
return myclass;
}
}
public class MC
{
public string Name { get; set; }
public int Next { get; set; }
}
public class SomeMainClass
{
public SomeMainClass()
{
var mc = new MC { Name = "test", Next = 0 };
var results = mc.CalculateValues();
}
}
There are many other ways to do class validation on a model, for example dataannotations comes to mind, or IValidatableObject works too. Keeping the validation separate from the class is a good idea.
//Complex properites are simple
public class MyComplextClass{
public List<MyThings> MyThings {get;set;}
public List<FileInfo> MyFiles {get;set;}
public List<DateTime> MyDates {get;set;}
}