I've got a computed column in a table that is used as a base table in a code-first inheritance hierarchy. What is weird is that the generated .ibmmx file is identical except for the value of the CreatedOn tag on line 3. If
I don't specify a [Table("TableName")] attribute in the derived
classes, I get the following exception trying to query the base table:
IdeaBlade.EntityModel.EntityServerException was unhandled by user code HResult=-2146233088 Message=Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Ssn'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Dob'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'SexCode'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'PrimaryLanguageID'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'EthnicityID'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'MaritalStatusID'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'ReligionID'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'EducationID'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Source=IdeaBlade.EntityModel Cancelled=false RemoteExceptionDetails=System.Data.SqlClient.SqlException (0x80131904): Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Ssn'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Dob'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'SexCode'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'PrimaryLanguageID'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'EthnicityID'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'MaritalStatusID'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'ReligionID'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'EducationID'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. Invalid column name 'Discriminator'. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException
exception, Boolean breakConnection, Action`1 wrapCloseInAction) at
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,
SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet
bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() at System.Data.SqlClient.SqlDataReader.get_MetaData() at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean
async, Int32 timeout, Task& task, Boolean asyncWrite) at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method, TaskCompletionSource`1 completion, Int32 timeout, Task&
task, Boolean asyncWrite) at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
at
System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand
entityCommand, CommandBehavior behavior) ClientConnectionId:dae25540-01a4-4b96-b6b9-8f38ed5d1905
RemoteExceptionName=System.Data.SqlClient.SqlException, System.Data,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 RemoteSource=.Net SqlClient Data Provider
RemoteStackTrace= at
System.Data.SqlClient.SqlConnection.OnError(SqlException exception,
Boolean breakConnection, Action`1 wrapCloseInAction) at
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException
exception, Boolean breakConnection, Action`1 wrapCloseInAction) at
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject
stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) at
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior,
SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet
bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() at System.Data.SqlClient.SqlDataReader.get_MetaData() at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean
async, Int32 timeout, Task& task, Boolean asyncWrite) at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method, TaskCompletionSource`1 completion, Int32 timeout, Task&
task, Boolean asyncWrite) at
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior
cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String
method) at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
at
System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand
entityCommand, CommandBehavior behavior) StackTrace: at
IdeaBlade.EntityModel.EntityManager.HandleEntityServerException(Exception
ex, Boolean tryToHandle, PersistenceOperation operation, Boolean
throwOnError) at IdeaBlade.EntityModel.EntityManager.<ExecuteServerQueryAsync>d__c7.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() at IdeaBlade.EntityModel.EntityManager.<ExecuteFetchAsync>d__c1.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at IdeaBlade.EntityModel.EntityQueryFinder.<ExecuteAsync>d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult() at IdeaBlade.EntityModel.EntityManager.<ExecuteQueryAsyncCore>d__69.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at
Fsl*gL.ViewModels.ShellViewModel.<LoadDataAsync>d__2.MoveNext() in
c:\Projects\Fsl*gL\Fsl*gL\ViewModels\ShellViewModel.cs:line 72 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at Fsl*gL.ViewModels.ShellViewModel.<OnActivate>d__6.MoveNext()
in c:\Projects\Fsl*gL\Fsl*gL\ViewModels\ShellViewModel.cs:line 80 InnerException:
Here are the classes:
public class EntityFacts : INotifyPropertyChanged { private readonly EntityAspect _entityAspect;
public EntityFacts(object entity) { _entityAspect = EntityAspect.Wrap(entity); _entityAspect.PropertyChanged += (s, args) => RaiseEntityFactsPropertyChanged(string.Empty); }
public EntityState EntityState { get { return _entityAspect.EntityState; } }
public bool IsNullEntity { get { return _entityAspect.IsNullEntity; } }
public bool IsPendingEntity { get { return _entityAspect.IsPendingEntity; } }
public bool IsNullOrPendingEntity { get { return _entityAspect.IsNullOrPendingEntity; } }
public bool HasErrors { get { return _entityAspect.ValidationErrors.HasErrors; } }
public EntityAspect.VerifierErrorsCollection ValidationErrors { get { return _entityAspect.ValidationErrors; } }
protected internal EntityAspect EntityAspect { get { return _entityAspect; } }
public void RaisePropertyChanged(string propertyName) { _entityAspect.ForcePropertyChanged(new PropertyChangedEventArgs(propertyName)); }
public event PropertyChangedEventHandler EntityPropertyChanged { add { _entityAspect.EntityPropertyChanged += value; } remove { _entityAspect.EntityPropertyChanged -= value; } }
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged { add { EntityFactsPropertyChanged += value; } remove { EntityFactsPropertyChanged -= value; } } protected event PropertyChangedEventHandler EntityFactsPropertyChanged;
protected void RaiseEntityFactsPropertyChanged(string propertyName) { if (null == EntityFactsPropertyChanged) return; EntityFactsPropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
[ProvideEntityAspect] [DataContract(IsReference = true)] //[RequiresAuthentication] public abstract class EntityBase { private EntityFacts _entityFacts;
[NotMapped] public EntityFacts EntityFacts { get { return _entityFacts ?? (_entityFacts = new EntityFacts(this)); } }
public virtual void Validate(VerifierResultCollection validationErrors) { }
[BeforeSet] internal void RemoveWhiteSpace(IEntityPropertySetInterceptorArgs args) { if (args.EntityProperty.DataType == typeof(string) && args.Value != null) args.Value = ((string)args.Value).Trim(); } }
[DataSourceKeyName("Fsl*gL")] public class Ent : EntityBase { [Key] [RequiredValueVerifier()] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Int32 EntID { get; set; }
[RequiredValueVerifier()] [Range(0, 1)] public Byte IsPerson { get; set; }
[StringLengthVerifier(MaxValue = 100, IsRequired = true)] public String LastName { get; set; }
[StringLengthVerifier(MaxValue = 35, IsRequired = false)] public String FirstName { get; set; }
[StringLengthVerifier(MaxValue = 35, IsRequired = false)] public String MiddleName { get; set; }
[StringLengthVerifier(MaxValue = 10, IsRequired = false)] public String Prefix { get; set; }
[StringLengthVerifier(MaxValue = 10, IsRequired = false)] public String Suffix { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] [RequiredValueVerifier()] public String FullName {
get // NOTE: getter is implemented in code so we don't have to commit
the changes to the DB to get the updated FullName { StringBuilder name = new StringBuilder(LastName);
if (FirstName != null) { name.Append(", ");
if (Prefix != null) name.Append(Prefix).Append(" ");
name.Append(FirstName);
if (MiddleName != null) name.Append(" ").Append(MiddleName);
if (Suffix != null) name.Append(" ").Append(Suffix); }
return name.ToString(); } set { } } }
[DataSourceKeyName("Fsl*gL")]
[Table("Client")] // NOTE: something about having a computed column in
the base table is requiring this to prevent run-time exceptions -
comment out to see error public class Client : Ent { [StringLengthVerifier(MaxValue = 11, IsRequired = false)] [Display(Name = "SSN", AutoGenerateField = true)] public String Ssn { get; set; }
[Display(Name = "Date of Birth", AutoGenerateField = true)] public DateTime? Dob { get; set; }
[StringLengthVerifier(MaxValue = 1, IsRequired = false)] public String SexCode { get; set; }
public Int32? PrimaryLanguageID { get; set; }
public Int32? EthnicityID { get; set; }
public Int32? MaritalStatusID { get; set; }
public Int32? ReligionID { get; set; }
public Int32? EducationID { get; set; } }
[DataSourceKeyName("Fsl*gL")] public class Fsl*gLDbContext : DbContext { public Fsl*gLDbContext(String connection) : base(connection) { // never try to create the database if it does not exist or match the current model. Database.SetInitializer((IDatabaseInitializer<DbContext>)null);
// DevForce already performs validation Configuration.ValidateOnSaveEnabled = false; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // don't try to create a table for this DevForce-generated type. modelBuilder.Ignore<EntityAspect>();
// don't assume table names are plural of entity class names modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); }
// only need to define enough to let DevForce discover all the entities public DbSet<Client> Clients { get; set; } }
Here is the SQL to create the tables:
CREATE TABLE [dbo].[Ent]( [EntID] [int] IDENTITY(10000,1) NOT NULL, [IsPerson] [tinyint] NOT NULL, [LastName] [varchar](100) NOT NULL, [FirstName] [varchar](35) NULL, [MiddleName] [varchar](35) NULL, [Prefix] [varchar](10) NULL, [Suffix] [varchar](10) NULL,
[FullName] AS ([LastName]+coalesce((((', '+coalesce([Prefix]+'
',''))+[FirstName])+coalesce(' '+[MiddleName],''))+coalesce('
'+[Suffix],''),'')) PERSISTED NOT NULL, PRIMARY KEY CLUSTERED ( [EntID] ASC )WITH
(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO
CREATE TABLE [dbo].[Client]( [EntID] [int] NOT NULL, [Ssn] [varchar](11) NULL, [Dob] [date] NULL, [SexCode] [char](1) NULL, [PrimaryLanguageID] [int] NULL, [EthnicityID] [int] NULL, [MaritalStatusID] [int] NULL, [ReligionID] [int] NULL, [EducationID] [int] NULL, CONSTRAINT [PK__EntDem__14C055AB1A14E395] PRIMARY KEY CLUSTERED ( [EntID] ASC )WITH
(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]
ALTER TABLE [dbo].[Client] WITH CHECK ADD CONSTRAINT [FK_Client_Ent] FOREIGN KEY([EntID]) REFERENCES [dbo].[Ent] ([EntID]) GO
ALTER TABLE [dbo].[Client] CHECK CONSTRAINT [FK_Client_Ent] GO
While
it is just a minor annoyance to have to specify the [Table] attribute, I
find it strange that even though the generated .ibmmx file is
identitcal, the runtime behavior is so different.
If I'm doing something stupid again, please let me know!
|