Reputation: 1403
I wrote myself a library to help with generic database lookups. When I use it I get a class that has all properties blank. However, the base class is properly filled. The product
variable is properly filled. How I can make the code fill the derived class (TModel entity
)? When I set breakpoint in the dataservice Create
method (comment inside code) these are the results in Locals/Autos window:
public class GenericLookupModelDataService<TModel, TViewModel> : object, IDisposable
where TModel : GenericLookupModel, new()
where TViewModel : GenericLookupViewModel, new()
public virtual void Create(TViewModel product, string username = "SYSTEM")
{
TModel entity = new TModel
{
is_active = product.Active,
value = product.Name,
created_on = product.CreatedOn,
created_by = product.CreatedBy,
modified_on = product.ModifiedOn,
modified_by = product.ModifiedBy
};
if (string.IsNullOrEmpty(entity.created_by)) //breakpoint here
entity.SetCreated(username);
if (string.IsNullOrEmpty(entity.modified_by))
entity.SetModified(username);
_db.Set<TModel>().Add(entity);
_db.SaveChanges();
}
TViewModel based on GenericLookupViewModel class:
public abstract class GenericLookupViewModel
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(300)]
public string Name { get; set; }
[Required]
public bool Active { get; set; }
[StringLength(50)]
[DisplayName("Record last modified by")]
public string ModifiedBy { get; set; }
[DisplayName("Record last modified Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime ModifiedOn { get; set; }
[StringLength(50)]
[DisplayName("Record created by")]
public string CreatedBy { get; set; }
[DisplayName("Record creation Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime CreatedOn { get; set; }
}
TModel based on GenericLookupModel class:
public abstract class GenericLookupModel : IActive, ICreated, IModified, IIdentity, IStringValue
{
public bool is_active { get; set; }
public string value { get; set; }
public DateTime created_on { get; set; }
public string created_by { get; set; }
public DateTime modified_on { get; set; }
public string modified_by { get; set; }
public int id {get;set;}
public void SetCreated(string creator = "SYSTEM")
{
created_by = creator;
created_on = DateTime.Now;
}
public void SetModified(string modifier = "SYSTEM")
{
modified_by = modifier;
modified_on = DateTime.Now;
}
public void ToggleActive()
{
is_active = !is_active;
}
}
Controller and Action:
public class PrimaryFocusController : GenericLookupViewModelController<PrimaryFocusViewModel,tblkp_PrimaryFocus>
{
public override ActionResult Create(PrimaryFocusViewModel lookup)
{
SetBrowsingUser(AppUser.Login);
return base.Create(lookup);
}
}
When I compile the library I get warning messages which might have to do something on this:
warning CS0108: 'DataLayer.tblkp_PrimaryFocus.id' hides inherited member 'MyLib.Model.GenericLookupModel.id'. Use the new keyword if hiding was intended.
warning CS0108: 'DataLayer.tblkp_PrimaryFocus.value' hides inherited member 'MyLib.Model.GenericLookupModel.value'. Use the new keyword if hiding was intended.
warning CS0108: 'DataLayer.tblkp_PrimaryFocus.is_active' hides inherited member 'MyLib.Model.GenericLookupModel.is_active'. Use the new keyword if hiding was intended.
warning CS0108: 'DataLayer.tblkp_PrimaryFocus.created_on' hides inherited member 'MyLib.Model.GenericLookupModel.created_on'. Use the new keyword if hiding was intended.
warning CS0108: 'DataLayer.tblkp_PrimaryFocus.created_by' hides inherited member 'MyLib.Model.GenericLookupModel.created_by'. Use the new keyword if hiding was intended.
warning CS0108: 'DataLayer.tblkp_PrimaryFocus.modified_on' hides inherited member 'MyLib.Model.GenericLookupModel.modified_on'. Use the new keyword if hiding was intended.
warning CS0108: 'DataLayer.tblkp_PrimaryFocus.modified_by' hides inherited member 'MyLib.Model.GenericLookupModel.modified_by'. Use the new keyword if hiding was intended.
The DataLayer.tblkp_PrimaryFocus is a class generated from EF using DB First approach.
UPDATE: User @code4life brought a good point - to have all those properties of the child classes marked as virtual
(tblkp_PrimaryFocus), but that would mean that I would need to mark all of them each time model is regenerated from EF Diagram - that's what I'm trying to avoid - modifying the EF-generated classes.
Upvotes: 0
Views: 164
Reputation: 2771
I know it is late to the game, but I stumbled in here struggling with some of the same issues. The first point for anyone to get into the code is to follow msdn. The main take-away to get started is add debug="true
to the top line in the .tt
file, e.g., <#@ template language="C#" debug="false" hostspecific="true"#>
becomes <#@ template language="C#" debug="true" hostspecific="true"#>
. Now you can debug the code by right clicking the .tt
files.
The place I think the questionnaire was referring is to simpleProperties
in the .tt
file. Here you can add override
or other keywords if need be :)
Upvotes: 1
Reputation: 7261
You can modify the T4 templates (.tt
files) to mark them as overriding or new as appropriate. The properties on the base type would have to be marked virtual of course.
I believe overriding would work as the behavior you observe seems to be due to your Create
method not being able to access the inherited properties (it only has the definitions of the base, and they're not virtual). That said, without getting too deep into your design I imagine this is not exactly what you want.
What you'd really want is to prevent the code generator from emitting the properties on the derived class to begin with so that all callers use the base definitions. I suggest you first look into the T4 templates again to see if you can't add rules that match against properties of your base type. Alternatively, consider custom attributes to match them.
It feels like there's a general way to solve this issue, so consider formulating a report for the EF team if you can confirm (I haven't thought about it very much).
Expect recommendations to switch to a Code-First approach however. Frankly, I'm tempted to recommend it to you myself.
Upvotes: 0