I build my DataContext with database-first and I have this entity:
public partial class Salutation
{
public int Id { get; set; }
public string SalutationShort { get; set; }
public string SalutationLong { get; set; }
public string LetterSalutation { get; set; }
}
and I use it like this:
var s = new Salutation()
{
SalutationShort = "Mr.",
LetterSalutation = "Mister"
};
context.Salutations.Add(s);
var xx = context.SaveChanges();
Problem: I can't force the database to generate a valid Id.
The first try give's '0' as primary key, following calls results in an error because '0' is already in use.
Did i miss something?
By the way, is there any reason why
protected override void OnModelCreating(DbModelBuilder modelBuilder)
isn't called??
Thanks
Peter
Related
public class UserDocuments
{
[Key]
[StringLength(30)]
public string UserID { get; set; } = string.Empty;
[Key]
public Guid DocumentID { get; set; } = Guid.Empty;
public UserType UserType { get; set; } = UserType.None;
public int Version { get; set; } = -1;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UserDocuments>()
.HasKey(x => new { x.UserID, x.DocumentID });
}
public static IEdmModel GetEdmModel()
{
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<UserDocuments>("UserDocuments");
return builder.GetEdmModel();
}
The detail error message I get is
"The entity set 'UserDocuments' is based on type
'DocServer2.Shared.Models.UserDocuments' that has no keys defined."
I cannot figure what is wrong with my code; I checked related entries here on SO, but cannot see a difference. I don't think that should be the case, but is it a problem to mix string and Guid in a composite key?
Edit [08/07/22]
I need to add [key] annotations to the two properties of UserDocuments that make up the key.
Using EfCore 1.1, I am trying to have a autogenerated column using ValueGeneratedOnAdd. The problem is i am always getting value as "0". Do i have to manually do anything with the database table ?
Here is my model
public class Contact
{
public int Id { get; set; }
// This needs to be auto generated
public Int32 ContactIndex { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public DateTime LastAccessed { get; set; }
}
This is how my OnModelCreating looks like
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Contact>()
.Property(c => c.ContactIndex)
.ValueGeneratedOnAdd();
// I tried following as well but it did't work
// .HasDefaultValueSql("IDENTITY(int, 1,1)");
;
}
ok I figured how to do it, but i really wanted to do that without using any annotations, and i still cannot figure out how to do it without annotations on model. So here is my solution.
You need to annotate your filed in the model like following
public class Contact
{
public int Id { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Int32 ContactIndex { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public DateTime LastAccessed { get; set; }
}
and add OnModelCreating in your context class. This will tell entity framework to ignore the column while adding or updating records. Make sure you calling method .ValueGeneratedAddOrUpdate( ). If you use only .ValueGeneratedAdd( ) you will get errors while making updates.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Contact>()
.Property(c => c.ContactIndex)
.ValueGeneratedOnAddOrUpdate();
;
}
Generate and run your migrations and your migrations should include "SqlServerValueGenerationStrategy.IdentityColumn"
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "ContactIndex",
table: "Contact",
nullable: false,
defaultValue: 0)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
}
I'll try create one-to-one relation using EF and Fluent API.
First class:
public class Game
{
public int Id { get; set; }
public Guid Token { get; set; }
public string Player { get; set; }
public virtual Field Field { get; set; }
public virtual ICollection<Move> Moves { get; set; }
public GameStatus Status { get; set; }
public DateTime StartTime { get; set; }
public DateTime? EndTime { get; set; }
public PlayerCode Winner { get; set; }
public Game()
{
Status = GameStatus.NoteDone;
StartTime = DateTime.UtcNow;
Winner = PlayerCode.None;
Field = new Field {Game = this};
Token = Guid.NewGuid();
}
}
Secong class:
public class Field : IEntity
{
public int Id { get; set; }
public virtual Game Game { get; set; }
public string CellsString { get; set; }
}
And configure relations in context
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Game>()
.HasRequired<Field>(g => g.Field)
.WithRequiredDependent(f => f.Game);
base.OnModelCreating(modelBuilder);
}
But after this relation in DB is not created. Tables look like this
I try many variations of Fluent configuration, but no one works for me. Where i do mistake?
You can specify a mapping for foreign key if you don't wish to add it as a property to your entity class.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Game>()
.HasRequired(g => g.Field)
.WithRequiredPrincipal(f => f.Game)
.Map(m => m.MapKey("GameId"));
}
You probably meant WithRequiredPrincipal, not WithRequiredDependent since you probably want that foreign key to be in the Field table.
I have the following simple entity:
public class Something{
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public int ID { get; set; }
public string NAME { get; set; }
public int STATUS { get; set; }
}
As you can see, I do not want the ID is generated from the database but I'm going to enter manually. This my DbContext class:
public class MyCEContext : DbContext {
...
public DbSet<Something> Somethings { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
string dbsch = "myce";
modelBuilder.Entity<Something>().ToTable("SOMETHING", dbsch);
}
}
There is nothing special here. But this code fails:
using (MyCEContext ctx = new MyCEContext()) {
Something t = new Something();
t.ID= 1;
t.NAME = "TEST";
t.STATUS = 100;
ctx.Somethings.Add(t);
ctx.SaveChanges();
}
This is the error:
The specified value is not an instance of type 'Edm.Decimal'
In general, allways EF try to send a value to an int primary key field, I get the edm.decimal error.
Any help?
As I commented on previous answer, I've found better solution, it is strange, but it works
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<TestEntity>().ToTable("TESTENTITY", "SCHEMENAME");
modelBuilder.Entity<TestEntity>().Property(p => p.Id).HasColumnName("ID").HasColumnType("INT");
modelBuilder.Entity<TestEntity>().Property(p => p.TestDateTime).HasColumnName("TESTDATETIME");
modelBuilder.Entity<TestEntity>().Property(p => p.TestFloat).HasColumnName("TESTFLOAT");
modelBuilder.Entity<TestEntity>().Property(p => p.TestInt).HasColumnName("TESTINT");
modelBuilder.Entity<TestEntity>().Property(p => p.TestString).HasColumnName("TESTSTRING");
}
and TestEntity looks like this
public class TestEntity
{
public int Id{ get; set; }
public string TestString { get; set; }
public int TestInt { get; set; }
public float TestFloat { get; set; }
public DateTime TestDateTime { get; set; }
}
I'm working with an application and data structure built upon ASP/ADO.NET and I'm converting part of it to ASP.NET MVC. In the data structure, there exists a "optional one-to-one" relationship, where both tables use the same primary key, and name. Basically this table can be considered an "optional extension" of the primary table. Here are samples of the model:
public class ZoneMedia
{
public int ZoneMediaID { get; set; }
public string MediaName { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public virtual ZoneMediaText MediaText { get; set; }
}
public class ZoneMediaText
{
public int ZoneMediaID { get; set; }
public string Text { get; set; }
public int Color { get; set; }
}
Obviously, EF 4.1 code first has an issue mapping this automatically. So I realize I must specify the mapping explicitly. I tried this:
modelBuilder.Entity<ZoneMedia>()
.HasOptional(zm => zm.ZoneMediaText);
modelBuilder.Entity<ZoneMediaText>()
.HasRequired(zmt => zmt.ZoneMedia)
.WithRequiredDependent(zm => zm.ZoneMediaText)
.Map(m => m.MapKey("ZoneMediaID"));
But it is still giving me an exception about the name of the primary key.
Schema specified is not valid. Errors:
(199,6) : error 0019: Each property name in a type must be unique. Property name 'ZoneMediaID' was already defined.
I'm a little stumped. I need to adapt to this non-conventional structure I realize in EF 4.1 it would be much easier to just add a unique PK to the optional relation and hold the foreign key relationship in the primary table, but I can't change the database layout. Any advice would be appreciated.
I hope i understood well.
This works for me:
public class ZoneMedia
{
public int ZoneMediaID { get; set; }
public string MediaName { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public virtual ZoneMediaText MediaText { get; set; }
}
public class ZoneMediaText
{
public int ZoneMediaID { get; set; }
public string Text { get; set; }
public int Color { get; set; }
public virtual ZoneMedia ZoneMedia { get; set; }
}
public class TestEFDbContext : DbContext
{
public DbSet<ZoneMedia> ZoneMedia { get; set; }
public DbSet<ZoneMediaText> ZoneMediaText { get; set; }
protected override void OnModelCreating (DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ZoneMedia>()
.HasOptional(zm => zm.MediaText);
modelBuilder.Entity<ZoneMediaText>()
.HasKey(zmt => zmt.ZoneMediaID);
modelBuilder.Entity<ZoneMediaText>()
.HasRequired(zmt => zmt.ZoneMedia)
.WithRequiredDependent(zm => zm.MediaText);
base.OnModelCreating(modelBuilder);
}
}
class Program
{
static void Main (string[] args)
{
var dbcontext = new TestEFDbContext();
var medias = dbcontext.ZoneMedia.ToList();
}
}
This Correctly create a FK_ZoneMediaTexts_ZoneMedias_ZoneMediaID in ZomeMediaTexts table, and the Foreign Key is the Primary Key.
EDIT: maybe it's worth pointing out that I'm using EF 4.3.0