Using EF, I've created a database with tables in a number of different schemas by using attributes:
[Table("AgeGroups", Schema = "codes")]
public class AgeGroup
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
[Required]
[MaxLength(1024)]
public string ResourceId { get; set; }
}
In the past, when using SqlMetal, schema names were prepended to the table names to differentiate between the different schemas:
context.Codes_AgeGroups
I can manually replicate this in EF, but I am hoping to come up with something more along the lines of:
context.Codes.AgeGroups
I struck upon the idea of adding an object to the EF context for each schema which would contain its respective tables. After some trial and error I arrived at the following:
public class ApplicationDataContext : CustomIdentityContext
{
public ApplicationDataContext() : base("DefaultConnection") {
Codes = new CodesSchema(this);
CustomerX = new CustomerXSchema(this);
CustomerY = new CustomerYSchema(this);
}
public ApplicationDataContext(string connection) : base(connection) {
Codes = new CodesSchema(this);
CustomerX = new CustomerXSchema(this);
CustomerY = new CustomerYSchema(this);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
...
}
public static ApplicationDataContext Create() {
return new ApplicationDataContext();
}
public class CodesSchema {
private ApplicationDataContext Context;
public DbSet<Codes.AgeGroup> AgeGroups { get { return Context.Codes_AgeGroups; } }
public DbSet<Codes.EducationLevel> EducationLevel { get { return Context.Codes_EducationLevel; } }
...
public CodesSchema(ApplicationDataContext context) {
Context = context;
}
}
public class CustomerXSchema {
private ApplicationDataContext Context;
public DbSet<CustomerX.SurveyData> SurveyData { get { return Context.CustomerX_SurveyData; } }
public CustomerXSchema(ApplicationDataContext context) {
Context = context;
}
}
public class CustomerYSchema {
private ApplicationDataContext Context;
public DbSet<CustomerY.SurveyData> SurveyData { get { return Context.CustomerY_SurveyData; } }
public CustomerYSchema(ApplicationDataContext context) {
Context = context;
}
}
public CodesSchema Codes { get; set; }
public CustomerXSchema CustomerX { get; set; }
public CustomerXSchema CustomerY { get; set; }
...
public virtual DbSet<Codes.AgeGroup> Codes_AgeGroups { get; set; }
public virtual DbSet<Codes.EducationLevel> Codes_EducationLevel { get; set; }
...
public virtual DbSet<CustomerX.SurveyData> CustomerX_SurveyData { get; set; }
public virtual DbSet<CustomerY.SurveyData> CustomerY_SurveyData { get; set; }
...
}
On the surface, this appears to be working, but I have some questions.
First, I wanted to make the virtual accessors protected, so they aren't directly accessible outside of the context class, but doing so results in the items within the schema classes coming back as null.
To be clearer:
context.Codes.AgeGroups
becomes null if try
protected virtual DbSet<Codes.AgeGroup> Codes_AgeGroups { get; set; }
Is there any other way to hide these virtual properties? Or, even better, a way to ensure they don't come back as null within the schema classes if make those properties protected?
My second question is related to how the Schema classes are being instantiated. I can't expressly pass a "ref" of the context into the schema class' constructor. This leaves me wondering: is the context object inside the schema class identical to the context object that was passed in (i.e. are they "equal")?
I'm sure this is probably overkill to replace an underscore with a period, but I like the idea of grouping tables by their schema. Feel free to chime in with why this might be a terrible idea.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…