Setting the Display Name of a model property using fluent API - entity-framework

Is there an equivalent fluent API approach to setting the display name of a model property in ef core? For example, how would you write the equivalent of the following in the OnModelCreating method of a dbcontext using HasAnnotation()?
[Display(Name = "Create Date")]
public DateTime CreateDate { get; set; }
I tried
entity.Property(e => e.CreateDate).HasAnnotation("DisplayName", "Create Date");

Can you use [override] keyword?
for instance
[Display(Name = "Create Date")]
public override DateTime CreateDate { get; set; }

please try this.
modelBuilder.Entity<YourEntityName>()
.Property(e => e.CreateDate)
.HasColumnName("Create Date");
in OnModelCreating method.

Related

EF Core Navigation property on ApplicationUser is always null

I'm trying to have a list of "buddies" for an ApplicationUser (just using the standard ASP NET Core Identity implementation).
In my mind, an ApplicationUser can have multiple Buddies, and a Buddy can have multiple ApplicationUser's. This means its a many to many relationship.
In line with EF Core's existing limitations with M2M relationships, I made a join class that looks like this:
public class ApplicationUserBuddies
{
public string UserGUID { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public string BuddyGUID { get; set; }
public ApplicationUser BuddyUser { get; set; }
}
I then configure ModelBuilder to recognise this relationship with in my OnModelCreating override
builder.Entity<ApplicationModels.ApplicationUserBuddies>().HasOne(x => x.ApplicationUser)
.WithMany(x => x.Buddies).HasForeignKey(x => x.UserGUID).IsRequired();
However, when I query through this table using EF, the "buddy" navigation property is always null. The actual string is set correctly (to that users GUID). This is how I am getting those details (note I am using Include):
var buddies = await _context.ApplicationUserBuddies.Include(x => x.BuddyUser).Where(x => x.UserGUID == UserGUID)
.Select(x => x.BuddyUser).ToListAsync();
Another strange thing is in my ApplicationUserBuddies table, I get a third column that I haven't set up anywhere called BuddyUserID
I think the issue I am having is because I have a many to many relationship that references one table (AspNetUsers table) and that could be affecting it.
How can I have a list of users as a navigation property from AspNetUsers and have it work correctly? Thanks everyone.
EDIT
I have changed my model to be in line with EF conventions
public class ApplicationUserBuddies
{
public string UserId { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public string BuddyUserId { get; set; }
public ApplicationUser BuddyUser { get; set; }
}
And my model builder now looks like this:
builder.Entity<ApplicationModels.ApplicationUserBuddies>().HasKey(x => new { x.UserId, x.BuddyUserId });
builder.Entity<ApplicationModels.ApplicationUserBuddies>().HasOne(x => x.ApplicationUser)
.WithMany(x => x.Buddies).HasForeignKey(x => x.BuddyUserId).IsRequired();
And now I have the columns UserId, BuddyUserId, and the erronerous BuddyUserId1. I think that this is essentially the same issue that I had at the outset.

Entity Framework Code First - Navigation property on Composite Primaty Key

Firebird 2.5
Entity Framework 5
FirebirdClientDll 3.0.0.0
Hi, I'm trying to access my legacy database with the Entity Framework (Code First).
I got the problem that the database does not use foreign keys...
public class CUSTOMERS
{
public int CUSTOMERID { get; set; }
public string NAME{ get; set; }
}
public class INVOICES
{
public int INVOICEID{ get; set; }
public int CUSTOMERID{ get; set; }
public virtual CUSTOMERS CUSTOMERS { get; set; }
}
public class INVOICEContext : DbContext
{
public DbSet<CUSTOMERS> CUSTOMERS{ get; set; }
public DbSet<INVOICES> INVOICES{ get; set; }
public INVOICEContext(DbConnection connectionString) : base(connectionString, false)
{
Database.SetInitializer<INVOICEContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
/*modelBuilder.Entity<INVOICES>().HasRequired(b => b.CUSTOMERS)
.WithMany()
.Map(p => p.MapKey("INVOICEID"));*/ //Doesn't work because INVOICEID is defined
modelBuilder.Entity<INVOICES>().HasKey(a => new { a.INVOICEID, a.CUSTOMERID});
modelBuilder.Entity<CUSTOMERS>().HasKey(a => new { a.CUSTOMERID });
base.OnModelCreating(modelBuilder);
}
}
Normally I could remove the property CUSTOMERID from the class INVOICES, but in this case it is part of the primary key...
I found many threads which suggested to use IsIndependent, but it seems to be removed from the Entity Framework 5 (or 4.1).
I hope you can understand my poor English and maybe give me a hint what I'm doing wrong ^^
I don't know what you mean with "the database does not use foreign keys". So, maybe the following is not the answer you are looking for. But I'd say that you can use your relationship mapping that is commented out in your code if you replace ...MapKey... by HasForeignKey and use CUSTOMERID instead of INVOICEID as the foreign key property:
modelBuilder.Entity<INVOICES>()
.HasRequired(b => b.CUSTOMERS)
.WithMany()
.HasForeignKey(b => b.CUSTOMERID);
The model and the rest of the mapping is fine in my opinion. Your relationship is an identifying relationship (that means that the foreign key is part of a composite primary key) which is a valid mapping with Entity Framework.
Try this ...
modelBuilder.Entity<INVOICES>()
.HasRequired(i => i.CUSTOMERS)
.WithMany()
.HasForeignKey(i => i.CUSTOMERID);

One to many relationship error

I have the following model, but I keep getting an error:
Unhandled Exception: System.InvalidOperationException: A relationship
multiplici ty constraint violation occurred: An EntityReference can
have no more than one r elated object, but the query returned more
than one related object. This is a no n-recoverable error.
public class Tournament
{
public long TournamentId { get; set; }
public string Title { get; set; }
public virtual User CreatedBy { get; set; }
}
public class User
{
public int UserId { get; set; }
}
modelBuilder.Entity<Tournament>()
.HasRequired(t => t.CreatedBy)
.WithOptional()
.Map(c => c.MapKey("CreatedById")); // correct column name
Your model fluent configuration entry is incorrect. Change it as follows
modelBuilder.Entity<Tournament>()
.HasRequired(t => t.CreatedBy)
.WithMany()
.Map(c => c.MapKey("CreatedById")); // correct column name
You'll have better luck managing Foreign keys if you modify you model a bit:
public class Tournament
{
public long TournamentId { get; set; }
public string Title { get; set; }
public virtual int CreatedById {get;set;}
public virtual User CreatedBy { get; set; }
}
and your mapping would look more like this:
modelBuilder.Entity<Tournament>()
.HasRequired(t => t.CreatedBy)
.WithMany()
.HasForeignKey(t => t.CreatedById); // correct column name
This way, when you create a new Tournament Entity you need only pass in the CreatedById and not the entire User object.
This can also happen if you have lazy loading enabled and not specifying all the navigation properties as Overridable (C# Virtual).

Entity Framework Data Annotations Set StringLength VarChar

I have this setting in my model:
[StringLength(250)]
public string Comment { get; set; }
to set the maximum length to 250 in the database which is great.
However it's set as nvarchar(250) when the database person was expecting varchar(250).
Can somebody please tell me how to set it as a varchar from the model as opposed to an nvarchar?
Use ColumnAttribute to give the datatype
[Column(TypeName = "VARCHAR")]
[StringLength(250)]
public string Comment { get; set; }
Or use fluent API
modelBuilder.Entity<MyEntity>()
.Property(e => e.Comment).HasColumnType("VARCHAR").HasMaxLength(250);
For some reason this older post keeps coming up in my search... so just FYI, using EF6 Core it's combined. The above answer errors out for me.
[Column(TypeName = "VARCHAR(250)")]
public string Comment {get;set;}
Visual Studio 2022 using Net 6 and EF Core 6, database first using the -DataAnnotations parameter creates the following attributes
/* Nullable column */
[StringLength(250)]
[Unicode(false)]
public string? Comment { get; set; }
/* Non-Nullable column */
[StringLength(250)]
[Unicode(false)]
public string Comment { get; set; } = null!;

Entity Framework 4.1 code-first KeyAttribute as non-identity column

I've got a problem with a code-first model I've got. Data is now in the database so I can't re-seed the database using a DropCreateDatabaseIfModelChanges class, but I need to change one table so that a bigint column is not an IDENTITY(1,1). I've managed to do this using SSMS but now my EF code is saying it's out of date.
This is the code for the table in question:
public class Vote {
[Required, Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public long FacebookUserId { get; set; }
[Required]
public Entity Entity { get; set; }
}
So I've changed my table schema, and my model (which I thought was the reflection of it, but I'm obviously wrong), but EF is still saying my model is out of date, and I can't re-seed the database to get it "perfect".
Any help would be much appreciated.
Thanks,
Benjamin
Using data annotation:
public class Customer
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CustomerID { get; set; }
}
Using fluent API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>().Property(c => c.CustomerID).HasDatabaseGeneratedOption(null);
base.OnModelCreating(modelBuilder);
}
referring to this post ...
It seems that entity framework expects by default that you insert into identity column.
to solve this try
modelBuilder.Entity<BOB>()
.HasKey(p => p.Id)
.Property(p => p.Id)
.StoreGeneratedPattern = StoreGeneratedPattern.None;
builder.Entity<BOB>().MapSingleType().ToTable("BOB");
or decorate your key in the POCO with ...
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Int64 PolicyID { get; set; }
Try add this to your OnModelCreating:
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
That should remove the exception that model is out of date but till this time you must always synchronize model and database manually.