I'm implementing a POCO in my project that represents a row in my database table. I'd like to modify one of the values in the constructor.
Unfortunately, it seems that the values are populated only after the constructor is run, so there's no way for me to perform my required logic. Is this a bug or by design?
I should probably mention that I'm using Code First.
public partial class CheckpointValue
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Column("saljare")]
public int SalesAgentId { get; set; }
[Column("volym")]
public int Value { get; set; }
[Column("datum")]
public DateTime Date { get; set; }
[Column("typ")]
public string Type { get; set; }
public CheckpointValue()
{
// Values empty... Why haven't they been populated when the constructor is run?
}
}
Unfortunately, it seems that the values are populated only after the
constructor is run, so there's no way for me to perform my required
logic. Is this a bug or by design?
This is by design. BTW, how you would be able to get these properties already populated during construction-time without providing constructor arguments?.
Maybe you're trying to implement your logic in the wrong place. If you're looking for implementing business rules, domain validation or who knows what, it should be done in another class. For example, your repository would be a good place to do things before returning the requested object.
public CheckpointValue GetById(Guid id)
{
CheckpointValue checkpointValue = YourDbContext.CheckpointValues.Find(id);
// Implement here what you wanted in your class constructor...
return checkpointValue;
}
Related
Using EF database-first, is it possible to create a duplicate of one of the classes, such that any query made comes back with an additional filter?
As an example: Given a class
public partial class Person
{
public Person()
{
this.Job= new HashSet<Appointments>();
}
public int PersonID { get; set; }
public int JobID { get; set; }
public string Forename { get; set; }
public string Surname { get; set; }
public virtual ICollection<Appointments> Appointments { get; set; }
}
Is it possible to construct a duplicate of the class in some way that functions like the existing class, but will only return results applied a "where Forename = 'David')
I can't overwrite the existing class (both cases need to be kept, and it'll be overwritten anyway)
My first thought was to simply create a seperate static class with methods that return an IQueryable< Persons>, but to then call that later, the context has been disposed - I don't think you can attach it to a new context?
The best you could do would be to add a function to your DbContext, in a partial class, that returns an IQueryable<Persons> with the filter already applied.
The partial class should have the same name as your actual context class. Any code in the partial class will be merged with the Database-First generated class, as if they were in the same file. It also won't get touched or overwritten by the code-generator if you regenerate the context. You can use this same concept to extend all kinds of code-generated classes (this is exactly the kind of use-case that partial classes were designed for).
public partial class MyDbContext
{
public IQueryable<Persons> FilteredPersons()
{
return this.Persons.Where(p => p.Forename =="David");
}
}
Then you can call it like this:
using (var myContext = new MyDbContext())
{
var query = myContext.FilteredPersons().Where(...some additional filter...);
var results = query.ToList();
}
You could probably also rig something up with an IDBCommandInterceptor, but that would be huge, hacky, ugly, and beyond the scope of a simple answer like this.
I'm still pretty new to these technologies. I've run into a small issue, and it's one that can be fixed by writing some lazy code...but OrmLite and ServiceStack streamline so many things, I'm wondering if there's a better way to do this.
So, I have a data model:
public class cctv_camera
{
[AutoIncrement]
public int I_id { get; set; }
public string I_sid { get; set; }
public string C_store_id { get; set; }
// .... others
}
This data model is mapped to a table, cctv_camera. There's another model (call it CamDetail) being sent to the client after some joins from this table. We are receiving back a CamDetail object from the client on a POST to save to the database and populating an instance of lp_cctv_camera with the data (new lp_cctv_camera().PopulateWith(CamDetail);).
Here's the thing: the I_sid column is a NOT NULL column with a default constraint that generates a hash for that row. It's something that the database is responsible for, so new items should not INSERT this column; it should be generated by the constraint.
Is there any way to db.Insert(lp_cctv_camera) while ignoring this column? I have tried the [Ignore] attribute on the definition, but we still need it in the definition to send existing I_sids out to the client. I really can't find anything in the docs. Any help is appreciated!
We've added an explicit [IgnoreOnInsert] attribute you can use to ignore specific properties on Insert which is available on v4.5.13 on MyGet.
Prior to v4.5.13 you can use the [Compute] attribute to get the similar behavior and ignore fields during inserts, e.g:
public class cctv_camera
{
[AutoIncrement]
public int I_id { get; set; }
[Compute]
public string I_sid { get; set; }
public string C_store_id { get; set; }
// .... others
}
From what I have read POCO classes should be persistence ignorant and should not contain references to repositories.
Q1. Given the above, how would I populate the QuestionBlocks collection? I have read that POCO's should contain behavior so you don't end of with an anemic model, so I'm kind of confused as how one is supposed to do that without persistence. If that's the case then what kind of behavior would you put in a POCO?
Ex:
public class Survey
{
public int SurveyId { get; set; }
public string Title { get; set; }
public int BrandId { get; set; }
public DateTime Created { get; set; }
public List<SurveyQuestionBlock> QuestionBlocks { get; set; }
[ResultColumn]
public string Name { get; set; }
/// <summary>
/// Constructor
/// </summary>
public Survey()
{
Created = DateTime.Now;
QuestionBlocks = new List<SurveyQuestionBlock>();
}
}
I would append another view: POCO states for objects which are not dependent on any framework. The wiki definition of a POJO is much more meaningful to me then the one for POCO:
http://en.wikipedia.org/wiki/Plain_Old_Java_Object
To paraphrase the wiki definition of the POJO, we can say that POCO object might not be forced to:
I. Extend prespecified class:
public class MyClass : AnyFramework.ObjectBase {...
II. Implement prespecified interfaces
public class MyClass : AnyFramework.IHaveDependency {...
III. Contain prespecified attribute
[AnyFramework.KeyAttribute]
public class MyClass {...
Given this (almost anything else is allowed) in the meaning of taking care about the object state. Other words, if object will check Business logic, it is correct.
But any POCO object can be used in a framework. Today it is mostly for ORM which is responsible for persistence. All application tiers are working with POCO objects, while data layer is responsible for loading and persisting (CRUD). This is mostly done via Proxies of these POCO objects.
So, POCO could be used as full business object, which can take care about itself (check correctness of collection items, properties...). This makes it different from DTO
Given the above, how would I populate the QuestionBlocks collection?
When reading from a database, the persistence infrastructure should populate the QuestionBlocks collection - reconstitution. Reconstruction should not invoke behavior, it should only set appropriate fields on the POCO. This is the responsibility of the repository. A repository is typically referenced from an application service, which sets up the stage for invoking entity behavior.
If that's the case then what kind of behavior would you put in a POCO?
The behavior in the POCO entity should be concerned with making changes to the entity itself as well as maintaining invariants - ie ensuring the integrity of the entity. In your example, the simplest kind of behavior on the POCO should be method for adding a new question block to the collection on the survey. Ideally, you would make many of the properties on the survey entity read-only:
public class Survey
{
public int SurveyId { get; private set; }
public string Title { get; private set; }
public int BrandId { get; private set; }
public DateTime Created { get; private set; }
public IList<SurveyQuestionBlock> QuestionBlocks { get; private set; }
public string Name { get; private set; }
public void AddQuestionBlock(string questionBlockInfo)
{
this.QuestionBlocks.Add(new SurveyQuestionBlock(...));
}
public Survey()
{
Created = DateTime.Now;
QuestionBlocks = new List<SurveyQuestionBlock>();
}
}
The persistence layer should be able to set the values of the read-only properties via reflection. You can go a step further and only expose the question blocks collection as a read-only collection to ensure that it can only be modified from within the entity itself.
I started by creating some models like this:
public abstract class EditableBase
{
public DateTime CreatedOn { get; set; }
public DateTime ModifiedOn { get; set; }
public int CreatedBy { get; set; }
public int ModifiedBy { get; set; }
}
public class Project : EditableBase
{
public int ProjectId { get; set; }
public string ProjectName { get; set; }
}
And I use this line when the app starts:
Database.SetInitializer<ModelContext>(
new DropCreateDatabaseIfModelChanges<ModelContext>());
A table called Projects is created with all the properties mentioned above as columns... this is exactly what I wanted.
However, now I need populate some default values when I issue a SaveChanges() on DbContext. When I save I need to update the ModifiedOn and ModifiedBy properties with the appropriate values.
Normally I would at least do the DateTime values on the database side (either a trigger or a stored procedure) however this is obviously not an option here since the database will be dropped anytime a class changes. And since I did code first I do not have a model designer that I can tweak the properties on.
What I would like to do is add a method in the EditableBase class that gets called when the SaveChanges() is executed, thus keeping all the logic involved in one place. Is it possible to do this? What is the best way to achieve my goal?
Override SaveChanges in your derived DbContext:
public override int SaveChanges()
{
foreach(var entry in ChangeTracker.Entries<EditableBase>())
{
var entity = entry.Entity;
if (entry.State == EntityState.Added)
{
entity.CreatedOn = ...;
entity.CreatedBy = ...;
}
else if (entry.State == EntityState.Modified)
{
entity.ModifiedOn = ...;
entity.ModifiedBy = ...;
}
}
return base.SaveChanges();
}
I'm only not sure if generic Entries will work directly with your base type becasue it is not actually mapped as base entity. There is also non generic version so you can rewrite it to more complex linq query or test each entry's entity type in loop.
Well, you have complete control over the code for your entities. I'd imagine you would probably want to implement an IPropertyChanged like pattern to update your properties.
Did consider the two options in this post where you do something on the setter (or constructor)?
The default attribute solution seems a good one.
I'm working on my first real MVC application and I'm trying to follow general OOP best practices. I'm refactoring some simple business logic that I had in a controller into my domain model. I've been doing some reading lately and it seems pretty clear that I should put the logic somewhere in a domain model entity class in order to avoid the "anemic domain model" anti-pattern.
The application will allow people to purchase leases for parking spaces. Rates are determined by the length of the spot and whether or not the customer is a member of the business park.
So I have entity classes in my domain model that look like this (simplified):
public class Customer
{
int ID { get; set; }
string Name { get; set; }
bool IsMember { get; set; }
}
public class ParkingSpace
{
int ID { get; set; }
int Length { get; set; }
}
public class ParkingSpaceLease
{
int ID { get; set; }
DateTime OpenDate { get; set; }
DateTime CloseDate { get; set; }
Customer Customer { get; set; }
ParkingSpace ParkingSpace { get; set; }
}
Edit: Just to clarify the LeaseQuote is not an entity class as it is just used to display the cost breakdown to perspective customers and is not persisted anywhere.
public class LeaseQuote
{
int SubTotal { get; set; }
int Discount { get; set; }
int Total { get; set; }
}
Now as a feature of the application I need to be able to generate quotes for different customer and parking space combinations. The quotes will normally be accessed outside the context of actually creating a lease such as when a customer calls up to inquire about a price.
So what is the best way to go about this? Does it make sense to instantiate a new ParkingSpaceLease object inside the controller just to call a GetQuote method on it?
var lease = new ParkingSpaceLease();
var quote = lease.GetQuote(length: 168, isMember: true);
return Json(quote);
Or should the LeaseQuote class have the method?
var leaseQuote = new LeaseQuote();
var quote = leaseQuote.GetQuote(length: 168, isMember: true);
return Json(quote);
It feels strange putting the logic in the actual ParkingSpaceLease class. I guess it feels kind of "heavy" to create a new lease object when I know that I'm not going to actually do anything with it other than access the GetQuote method which seems kind of like a separate service.
So where should the GetQuote method go and why should it go there?
It almost sounds like your LeaseQuote isn't an entity and more of a business level class. I mean, you're not storing it in the database anywhere, are you? And it's not a part of another data object.
When I see this
Now as a feature of the application I need to be able to generate quotes for different customer and parking space combinations. The quotes will normally be accessed outside the context of actually creating a lease such as when a customer calls up to inquire about a price.
I think of a method signature like this
public LeaseQuote GetQuote(Customer customer, ParkingSpace parkingSpace, int length)
But with that in mind, I'd probably also want to store information about the cost of the parking space within the ParkingSpace entity and (if applicable) the customer's discount in the Customer entity.
Where would this stuff go? In a model class (business model, not LINQ or Entity model) that accesses your entities and serves as a provider for your controller.
Now I know that's not using your models exactly as written. And it could just be personal bias. But when I think about data models and data entities, they should not have any addon methods outside of what's coming back from the database. They should just represent the data unaltered as it appears in the database. If you're acting on the data, that belongs in a tier above the data entities.
Update:
What I am curious about from your example is why one would want to pass the full Entity objects (Customer and Parking Space) versus just the properties needed to perform the calculation?
It depends on your standard of code. Exposing the entity itself could be dangerous if the consuming code manipulates the entity. I prefer passing the entity mainly because that's what I'm used to. But I'm also careful not to manipulate the entity on the way in. That, and I think the method signature reflects what the GetQuote method is focused on; it's related to a customer and a parking space.
I could also make the case that if more fields go into the Entity later that can effect the GetQuote method, then the method signature doesn't have to change. In this case, only the implementation for GetQuote has to change.
Short answer: Preference.
Just make GetQuote a static method in ParkingSpaceLease.
I think you may have your object model slightly askew, which would lead to your concern about the lease being the wrong place from which to get a quote. It seems to me that a lease would be wholly composed by the parking space which is being leased, and would be related only to the customer purchasing the lease. IOW:
public class ParkingSpace
{
int ID { get; set; }
int Length { get; set; }
IEnumerable<ParkingSpaceLease> Leases { get; set; }
LeaseQuote GetQuote(Customer customer/*, other relevant parameters */) { ... }
}
public class ParkingSpaceLease
{
int ID { get; set; }
DateTime OpenDate { get; set; }
DateTime CloseDate { get; set; }
Customer Customer { get; set; }
}
public class LeaseQuote
{
//Properties
ParkingSpaceLease GetLease();
}
EDIT I missed the part about the LeaseQuote being a separate class.