Page 1 of 1

StoreGeneratedPattern, DefaultValue and fluent mapping

Posted: Tue 30 Aug 2011 06:38
by magnus
The technique described in this blog post doesn't seem to work with the DbContext generated by Entity Developer when fluent mapping is enabled. I noticed that the example uses ObjectContext, but I've verified that it works fine with DbContext when fluent mapping is disabled, which I guess is because it finds the specified default values in the XML mapping files. Is this a known limitation, a bug, or is there something else I'm missing?

The example in the link produces the following SQL with ObjectContext, or with DbContext without fluent mapping:

Code: Select all

DECLARE
  updatedRowid ROWID;
BEGIN
INSERT INTO INFO.PRODUCTS("Id", "FunctionGeneratedValue", "ProductName", "Price", "ModifiedBy", "LastModified")
VALUES (MY_SEQUENCE.NEXTVAL, MY_FUNCTION(), :p0, :p1, USER, current_timestamp)
RETURNING ROWID INTO updatedRowid;
OPEN :outParameter FOR SELECT "Id", "FunctionGeneratedValue" FROM INFO.PRODUCTS WHERE ROWID = updatedRowid;
END;
And here's the generated (failing) SQL with fluent mapping enabled:

Code: Select all

DECLARE
  updatedRowid ROWID;
BEGIN
INSERT INTO INFO.PRODUCTS("ProductName", "Price")
VALUES (:p0, :p1)
RETURNING ROWID INTO updatedRowid;
OPEN :outParameter FOR SELECT "Id", "FunctionGeneratedValue", "ModifiedBy", "LastModified" FROM INFO.PRODUCTS WHERE ROWID = updatedRowid;
END;
The latter SQL statement, for obvious reasons, gives a DbUpdateException with the message: {"ORA-01400: cannot insert NULL into (\"INFO\".\"PRODUCTS\".\"Id\")\nORA-06512: at line 4"}

Here's the (auto-generated) fluent mapping code I'm using:

Code: Select all

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

            #region Products

            modelBuilder.Entity()
                .HasKey(p => new { p.Id })
                .ToTable("PRODUCTS", "INFO");
            // Properties:
            modelBuilder.Entity()
                .Property(p => p.Id)
                    .IsRequired()
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            modelBuilder.Entity()
                .Property(p => p.ProductName)
                    .IsRequired()
                    .HasMaxLength(160)
                    .IsUnicode(false);
            modelBuilder.Entity()
                .Property(p => p.Price);
            modelBuilder.Entity()
                .Property(p => p.FunctionGeneratedValue)
                    .IsRequired()
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            modelBuilder.Entity()
                .Property(p => p.ModifiedBy)
                    .IsRequired()
                    .HasMaxLength(30)
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)
                    .IsUnicode(false);
            modelBuilder.Entity()
                .Property(p => p.LastModified)
                    .IsRequired()
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);

            #endregion

            #region Disabled conventions

            modelBuilder.Conventions.Remove();
            modelBuilder.Conventions.Remove();

            #endregion

        }

Posted: Wed 31 Aug 2011 14:43
by Shalex
This http://social.msdn.microsoft.com/Forums ... fabeb258e4 response is actual till now: EF fluent mapping doesn't support the possibility of setting default value. Default value can be set only with the help of XML-mapping (edmx) at the moment.

Posted: Thu 01 Sep 2011 06:41
by magnus
OK, thanks for the information. The only thing we actually need this for is sequence numbers for primary keys, and using triggers is not an option because that would break legacy code. Can you think of some other reasonably simple way to achieve the same results while using fluent mapping, given a set of entities, (almost) all of which have a corresponding sequence with a predictable name?

Posted: Fri 02 Sep 2011 11:02
by Shalex
We do not know about an alternative.