Haytham Bustami
Haytham Bustami

Reputation: 69

Must Be Mapped. It has no default value and is not nullable

I'm just starting to learn EF. The problem I'm facing is with TPH. The example below is from the EF recipes by apress. The table is basically this:

CREATE TABLE [Chapter2].[Employee](
[EmployeeId] [int] IDENTITY(1,1) NOT NULL,
[EmployeeType] [int] NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[Salary] [decimal](18, 0) NOT NULL,
[Wage] [decimal](18, 0) NOT NULL,
 CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED 
(
    [EmployeeId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

After creating table and importing it into EF. I made two entities, one FullTimeEmployee and HourlyEmployee. I'm setting the condition under employee type to 1 for the full time one and 2 for the hourly one. I'm, of course deleting the property from the main Employee entity.

<edmx:Mappings>
  <Mapping Space="C-S" xmlns="http://schemas.microsoft.com/ado/2009/11/mapping/cs">
    <EntityContainerMapping StorageEntityContainer="EFRecipesModel1StoreContainer" CdmEntityContainer="EFRecipesEntities1">
      <EntitySetMapping Name="Employees">
        <EntityTypeMapping TypeName="IsTypeOf(EFRecipesModel1.Employee)">
          <MappingFragment StoreEntitySet="Employee">
            <ScalarProperty Name="EmployeeId" ColumnName="EmployeeId" />
            <ScalarProperty Name="LastName" ColumnName="LastName" />
            <ScalarProperty Name="FirstName" ColumnName="FirstName" />
          </MappingFragment>
        </EntityTypeMapping>
        <EntityTypeMapping TypeName="IsTypeOf(EFRecipesModel1.FullTimeEmployee)">
          <MappingFragment StoreEntitySet="Employee">
            <ScalarProperty Name="EmployeeId" ColumnName="EmployeeId" />
            <ScalarProperty Name="Salary" ColumnName="Salary" />
            <Condition ColumnName="EmployeeType" Value="1" />
          </MappingFragment>
        </EntityTypeMapping>
        <EntityTypeMapping TypeName="IsTypeOf(EFRecipesModel1.HourlyEmployee)">
          <MappingFragment StoreEntitySet="Employee">
            <ScalarProperty Name="EmployeeId" ColumnName="EmployeeId" />
            <ScalarProperty Name="Wage" ColumnName="Wage" />
            <Condition ColumnName="EmployeeType" Value="2" />
          </MappingFragment>
        </EntityTypeMapping>
      </EntitySetMapping>
    </EntityContainerMapping>
  </Mapping>
</edmx:Mappings>

THe error I'm getting is:

Error3023: Problem in maaping fragments starting at line 51 column: Employee.Salary in table Employee must be mapped. It has no default value and is not nullable.

I read around and saw a suggestino up update the SSDL which in a way didn't make sense to me:

    <edmx:StorageModels>
  <Schema Namespace="EFRecipesModel1.Store" Provider="System.Data.SqlClient" ProviderManifestToken="2012" Alias="Self" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
    <EntityType Name="Employee">
      <Key>
        <PropertyRef Name="EmployeeId" />
      </Key>
      <Property Name="EmployeeId" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />
      <Property Name="EmployeeType" Type="int" Nullable ="false" DefaultValue="1"/>
      <Property Name="FirstName" Type="nvarchar" MaxLength="50" Nullable="false" />
      <Property Name="LastName" Type="nvarchar" MaxLength="50" Nullable="false" />
      <Property Name="Salary" Type="decimal" Precision="18" Scale="0" Nullable="false" />
      <Property Name="Wage" Type="decimal" Precision="18" Scale="0" Nullable="false" />
    </EntityType>
    <EntityContainer Name="EFRecipesModel1StoreContainer">
      <EntitySet Name="Employee" EntityType="Self.Employee" Schema="Chapter2" store:Type="Tables" />
    </EntityContainer>
  </Schema>
</edmx:StorageModels>

note that I added the Nullable and Default value for EmployeeType. This still doesn't solve the problem.

Could I get some help as to why I'm having such a problem mapping properly?

Upvotes: 4

Views: 5922

Answers (2)

noob54
noob54

Reputation: 1

I ran into a similar issue and what I done was;

Right-click the "Main" entity, and select Properties. Set the Abstract attribute to true, which marked the "Main" entity as abstract.

Just thought I would share this as setting a default value for me stopped ef from complaining but the value was not available when needed in my program .

Upvotes: 0

Gert Arnold
Gert Arnold

Reputation: 109185

To me it makes more sense to add DefaultValue to Salary and Wage in the store model:

<Property Name="Salary" Type="decimal" Nullable="false" DefaultValue="0"/>
<Property Name="Wage" Type="decimal" Nullable="false" DefaultValue="0"/>

And also in the conceptual model (in the edmx designer).

It would also make sense to add them as default constraints to the fields in the database (although EF does not copy these constraints to the edmx when the model is generated from the database).

Anyhow, the fields must have a default value since they are not nullable in the database, and none of the concrete entities supply values for both fields.

Upvotes: 2

Related Questions