I try save complex class inside another class. TypeMask contained inside Entity. TypeMask overloads ToString method, and when time to save Entity comes, a want automaticaly save Mask prop in string form, and when I need load Entity class back automaticaly convert this string to TypeMask(constructor of TypeMask can build TypeMask using string). So what have I overload or from what have I inherit to make it real?
public class Entity
{
[Key]
public int Id { get; set; }
public TypeMask Mask { get; private set; }
}
Here's a way to do this:
public class Entity
{
private TypeMask _typeMask;
[Key]
public int Id { get; set; }
public string TypeMaskString { get; set; }
[NotMapped]
public TypeMask Mask
{
get
{
if (this._typeMask == null && !string.IsNullOrEmpty(TypeMaskString))
{
this._typeMaks = new TypeMask(this.TypeMaskString);
// Or some other way to create a TypeMask from string.
}
return this._typeMask;
}
set
{
this._typeMask = value;
this.TypeMaskString = value.ToString();
}
}
}
There are some things to keep in mind here. When your code makes modifications to a TypeMask object you have to set the object again to update TypeMaskString. Of course, this is error-prone and elaborate, so you want to make sure that TypeMask can be modified through only one method (maybe a method in Entity).
The alternative is to have a property like this (skipping null checks for brevity)
public string TypeMaskString
{
get
{
return this.TypeMask.ToString();
}
set
{
this.TypeMask = new TypeMask(this.TypeMaskString);
}
}
Now the TypeMask object can be modified and TypeMaskString will always return an up-to-date value. But this may hit performance because it potentially converts TypeMask to and from string many times. More often than you may suspect, because EF's change tracker will always read TypeMaskString when it executes DetectChanges, which is a process that runs repeatedly.
Related
I'm currently building a test application that manages parts for engineers, and I've hit a snag. I have a few different classes, including PartsModel and EngineerModel, and I want to update a list of parts that an engineer has, but I'm mindful of issues from either transposed parameters or from structuring the code in a way that unnecessarily couples to a particular class.
The two classes, with some relevant properties:
public class PartModel
{
public int PartId { get; private set; }
public string PartTitle { get; set; }
public string PartDescription { get; set; }
public int Quantity { get; set; }
public int MinimumStock { get; set; }
public void AddToStock (int quantityToAdd) {
Quantity += quantityToAdd;
}
public void RemoveFromStock (int quantityToRemove) {
Quantity -= quantityToRemove;
CheckMinimumStock();
}
}
public class EngineerModel
{
public int EngineerId { get; private set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<PartModel> PartsInStock { get; set; } = Factory.CreatePartsList();
}
As you can see, each engineer has a list of parts they have in stock via a List<PartModel>. I want to pass another list to this one so that I can update it respectively (incrementing or decrementing quantities, and then adding or removing parts to the list as necessary).
The first warning bell is that it takes two inputs of the same type, and is going to fill one from the other one (which isn't needed afterwards), so you're essentially modifying one input and destroying the other. To me, this presents a danger of the inputs getting transposed and the wrong list being either returned or updated (depending on whether it returns or just acts on the list). Because it removes items that have no quantity, it can't check the list length and just update the longer one, because there are possible cases where the engineer's list is shorter (maybe they're a new engineer, or maybe they just had a large shipment of parts sent when they were running low on stock). If it did just keep parts with quantity zero, then you're threatening scalability of both engineers and parts (not to mention any other objects that use the same operation).
So, put it as a method in the EngineerModel class and operate on PartsInStock, right? But what about when I want to use the same operation on other classes (e.g. if I have a list of parts associated to a work task)? Then I extract the method out to another class and... I'm passing the two lists as parameters in the method, so I'm back to where I was.
Am I being reasonable in not wanting to have two parameters of the same type, and how do I structure the code to deal with this, but without creating unnecessary coupling? If I'm not being reasonable, what am I overlooking?
Use an extension method
Thanks to #DavidBrowne-Microsoft for clarifying this. By defining an extension method for List<PartModel>, it only needs the one parameter - the list containing the updates (foreach below based on #Valentin's answer to this question).
public static class PartsHandler
{
public static List<PartModel> UpdateStockQuantitiesWith(this List<PartModel> stockToBeUpdated, List<PartModel> stockUpdates) {
foreach ( var part in stockUpdates )
{
var partToBeUpdated = stockToBeUpdated.FirstOrDefault(x => x.PartId == part.PartId);
if ( partToBeUpdated != null )
{ partToBeUpdated.Quantity += part.Quantity; }
else
{ stockToBeUpdated.Add(part); }
}
stockToBeUpdated.RemoveAll(x => x.Quantity <= 0);
return stockToBeUpdated;
}
}
Now any class that needs to implement this can simply call it in a method on the respective property. For example, in the EngineerModel class, it can operate on the PartsInStock property:
public void AddPartsToStock(List<PartModel> partsSent) {
PartsInStock.UpdateStockQuantitiesWith(partsSent);
}
What would be the easiest and least labour intensive (from the software POV) for me to be able to get a property (to be read and modified) from an entity generated via the Entity Framework?
Example (and simplified code) below:
// <auto-generated> from Entity Framework
public partial class tblCustomer
{
public int CustomerID { get; set; }
public string Status { get; set; }
}
For instance I would like:
tblCustomer customer = new tblCustomer();
int pCustomerID = customer.GetFieldByName("CustomerID");
pCustomerID = 100;
I've read a lot of answers about Reflection, but also comments that it's heavy processing (may be a bit excessive for my needs).
My example code may seem rather simplistic (so a solution would be rather pointless for that, the real code is based on large tables), but if there was some sort of GetFieldByName function I could reduce my code significantly as I have a lot of repetitious code doing the same stuff (just to different columns).
If I understand your problem correctly, I think you can use the changetracker for this (if the entity is in the context already).
dbContext.Entry(customer).CurrentValues["CustomerID"]
will give you the value of CustomerID for the customer object, provided it is attached to the dbContext instance.
If it is not part of the context, you can use Attach() to attach it first, or use Add(), if it's supposed to be a new record.
If you don't like to use Reflection the only way that i know is using a dictionary in your entities and also you can put all these stuff in a base class and your entities inherit it for example like that:
[Serializable]
public class BaseEntity
{
Dictionary<string, object> _dic;
public BaseEntity()
{
_dic = new Dictionary<string, object>();
}
public object this[string propertyName]
{
get
{
return _dic[propertyName];
}
set
{
_dic[propertyName] = value;
}
}
}
public class tblCustomer : BaseEntity
{
public int CustomerID
{
get
{
return (int)this["CustomerID"];
}
set
{
this["CustomerID"] = value;
}
}
public string Status
{
get
{
return (string)this["Status"];
}
set
{
this["Status"] = value;
}
}
}
tblCustomer customer = new tblCustomer();
int pCustomerID = customer["CustomerID"];
and about performance cost of Reflection you can for first time store your memberInfos in a static field and use it for all instances.
LogEvent represents information like log level, message, user, process name, ...
Some of these properties' values require pretty much effort for generation, e. g. the process name. Those properties' generated values are usually not changed, BUT despite this fact it should be possible to change them.
I considered the prototype pattern starting with a protoype, whose generic properties are pre-allocated. The protoype stays the same object during the lifetime of the application, but its properties' values might change as described above. New LogEvent objects should use the current prototype's values, objects created before the change should continue using the old values, that means, referencing the prototype from the "real" LogEvent object is not an option.
However the "real" LogEvent requires some properties to be not null, whereas this requirement is not useful for the prototype. I would like to prevent invalid objects of LogEvent. However if I use usual protoype pattern I would have to add a constructor to create the prototype, but this constructor would not create a valid object and I want to avoid, that an invalid object (the prototype itself or a clone of it) is used accidentally.
I spent some time on searching a solution, but the approaches listed below are pretty ugly. I hope, that there is an elegant solution. Meanwhile I tend to option 3, because 1 and 2 do not seem to be clean.
General structure
public interface ILogEvent
{
string PreAllocatedProperty1 { get; set; }
string PreAllocatedProperty2 { get; set; }
string IndividualProperty1 { get; set; }
string IndividualProperty2 { get; set; }
}
Option 1
Pros
LogEventPrototype can not be used as ILogEvent.
properties do not have to be declared in multiple classes
Cons
properties have to be mapped manually
static methods => interface for prototypes not possible
Code
class LogEventPrototype
{
public string PreAllocatedProperty1 { get; set; }
public string PreAllocatedProperty2 { get; set; }
public string IndividualProperty1 { get; set; }
public string IndividualProperty2 { get; set; }
public LogEventPrototype() { GeneratePreAllocatedProperties(); }
private void GeneratePreAllocatedProperties()
{
// if you invoke the helper functions later again,
// they might return different results (e. g.: user identity, ...)
PreAllocatedProperty1 = Helper.ComplexFunction();
PreAllocatedProperty2 = Helper.AnotherComplexFunction();
}
}
class LogEvent : LogEventPrototype, ILogEvent
{
// just for creating the prototype, object will be in an INVALID state
private LogEvent() : base() { }
// object will be in a VALID state
public LogEvent(string individualProperty2)
: this()
{
if (individualProperty2 == null)
throw new ArgumentNullException();
IndividualProperty2 = individualProperty2;
}
public static LogEvent FromPrototype(LogEventPrototype prototype)
{
// clone manually
return new LogEvent(prototype.IndividualProperty2)
{
IndividualProperty1 = prototype.IndividualProperty1,
PreAllocatedProperty1 = prototype.PreAllocatedProperty1,
PreAllocatedProperty2 = prototype.PreAllocatedProperty2
};
}
}
Option 2
Similar to option 1, but:
Pros
it is "ensured", that LogEventPrototype is never instantiated, it is just used as return type
no manual mapping
Cons: It seems to be hacky.
class LogEventPrototype
{
// properties ... (same as in option 1)
protected LogEventPrototype()
{
GeneratePreAllocatedProperties();
}
}
class LogEvent : LogEventPrototype, ILogEvent
{
// constructors same as in option 1; FromPrototype() removed
public static LogEventPrototype CreateProtoype()
{
return new LogEvent();
}
public static LogEvent FromPrototype(LogEventPrototype prototype)
{
if(prototype.IndividualProperty2 == null)
throw new ArgumentException();
return (LogEvent)prototype;
}
public static LogEventPrototype CreateProtoype()
{
return new LogEvent();
}
}
Option 3
Do not use a dedicated class for prototypes, but make the LogEvent constructor public and risk invalid LogEvent objects. Use a Validate() method instead and hope, that a client does not forget to use it.
I'm currently finishing work on object change log functionality and would like to polish few things. Since we have a lot of web forms/reports where historical data should appear, I'm wondering if there is a way to implement that without changing controls/reports.
Currently, I have this situation:
public class Foo {
public string Property1 { get; set; }
public DateTime CreatedDate { get; set;}
public string GetHistoricalValue(string propertyName)
{
HistoryHelper historyHelper = CreateHistoryHelper(this);
return historyHelper.GetHistoricalValue(propertyName, CreatedDate);
}
...
public class HistoryHelper {
public string GetHistoricalValue(string propertyName, DateTime date) {
...
So, when someone wants to fetch historical data for Property1:
string historicalValue = fooInstance.GetHistoricalValue("Property1");
It's obvious that this approach requires a lot of changes in current application.
Is there a way to make Foo class returns historical value when I access Property1 in regular way:
string historicalValue = fooInstance.Property1;
Something like dynamically generating subclass with overriden properties or some other solution?
Is this possible?
INITIAL ANSWER
Something like this:
public class Foo {
public bool HistoricalMode { get; set; }
private string _property1;
public string Property1 {
get {
if (HistoricalMode) {
return GetHistoricalValue("Property1");
} else {
return _property1;
}
set {
if (HistoricalMode){
throw new NotSupportedException("Updates not possible in historical mode.");
} else {
_property1 = value;
}
}
}
public DateTime CreatedDate {
get {
// Similar pattern as above
}
set {
// Similar pattern as above
}
}
public string GetHistoricalValue(string propertyName) {
HistoryHelper historyHelper = CreateHistoryHelper(this);
return historyHelper.GetHistoricalValue(propertyName, CreatedDate);
}
}
Basically the idea is to keep a boolean in your objects which indicates in the object is in 'history mode'. If so, use your helper method. If not, normal properties getters/setters apply.
UPDATE
The solution to this question I think would require a change in your framework (if you have a single framework for all your applications). I would seek the solution in the way you are loading your objects. Hopefully you can detect when an object is required in 'historical mode' and when in 'normale mode'. Where you now 'just read' the object (record) from the database, in historical mode you need to compose the original object (from when the change happened) from your change log functionality. That way, all your current application can (hopefully) stay the way they are. The 'only' change you need to do is at the repository class.
This is all just speculation btw.
Can you easily affect how Foo instances are created? If so, you can for example create derived class HistoricalFoo : Foo, make Property1 virtual and use its getter to change its behaviour. Then use HistoricalFoo whenever you need historical data. It is not a very clean object model, but can get the job done.
public class Foo
{
protected string _property1;
public virtual string Property1
{
get { return _property1; }
set { _property1 = value; }
}
public DateTime CreatedDate { get; set;}
/* ... */
}
public class HistoricalFoo : Foo
{
public override string Property1
{
get
{
return GetHistoricalValue("Property1");
}
}
}
If this is not applicable, it's possible to embed some decision logic into the Property1 getter. In this scenario, you would have to change the internal state of the Foo instance - for example by setting a boolean flag IsInHistoryMode. Changing object states can be very tricky though, expecially in multithreaded environment.
public class Foo
{
public bool IsInHistoryMode { get; set; }
protected string _property1;
public virtual string Property1
{
get
{
if(IsInHistoryMode)
{
return GetHistoricalValue("Property1");
}
return _property1;
}
set
{
_property1 = value;
}
}
public DateTime CreatedDate { get; set;}
/* ... */
}
Is it possible to have a HasMany relationship of a basic type such as String, on an ActiveRecord class, without the need for creating another entity such as (TodoListItem) to hold the value.
[ActiveRecord]
public class TodoList
{
[PrimaryKey]
public int Id
{
get { return _id; }
set { _id = value; }
}
[HasMany(typeof(string)]
public IList<string> Items
{
get { return _items; }
set { _items= value; }
}
}
Can anyone help?
Yes, you can do this. You can map a one-to-many relation to a built-in or simple type (value type or string) rather than a persisted type.
You'll need to specify the ColumnKey, Table and Element params in the HasMany attribute declaration to get it to wire up properly. You have to have a surrogate key column so the AR can handle updates and cascades, and then Element tells AR which column in the table holds the simple value it will use to make the list.
[HasMany(typeof(string), Table="ToDoList_Items",
ColumnKey = "ListItemID", Element = "Item")]
public IList<string> Items { get; set; }
(or something similar - I haven't got a compiler handy on this box to check it; but per the API docs it ought to work.)
Speaking of which, if you haven't already had a look, http://api.castleproject.org is kinda indispensible for any work with the Castle stack.
In ActiveRecord, your types map to a record in a table (by default). It seems like you are confusing how this type should map to your table.
The MyClass type should have a definition something like this (excluding the PK settings):
[ActiveRecord(Table = "MyTable")]
public class MyClass : ActiveRecordBase<MyClass>
{
[Property]
public int Id { get; set; }
[Property]
public int MyClassId { get; set; }
[Property]
public string ListItem { get; set; }
}
Then, to load the list:
public void LoadMyClasses()
{
MyClass[] results = MyClass.FindAll();
}
I'd suggest you spend some time with the ActiveRecord documentation (or tutorial) as that should also help clear up any confusion.