In Entity Framework 7 which property Attribute creates an index in code first? - data-annotations

In Entity Framework 7 (7.0.0-rc1-final) which property Attribute creates an index?
I would normally add an index to a sql table to improve look up times so I assume I need to specify this in my class?
public class Account
{
[Key]
[Required]
public int AccountId { get; set; }
[Required] <-- How do I make this an Index in Sql Server?
public int ApplicationUserId { get; set; }
}
I assume [Index] would do it but this is not recognised.
How do I index the ApplicationUserId column?

Use the fluent API in your DbContext class:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Account>()
.HasIndex(b => b.ApplicationUserId);
}

Here is a workaround:
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class IndexAttribute : Attribute
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var property in entity.GetProperties())
{
if (property.PropertyInfo != null && property.PropertyInfo.GetCustomAttributes<IndexAttribute>().Any())
{
entity.AddIndex(new[] { property });
}
}
}
}

Related

Self-referencing table in EF6

I thought this was going to be easy... I have a situation where I have a table Module, which can contain "base" modules, and "compound" modules (that are made up from 1-n base modules).
So I have these two tables in SQL Server 2014:
CREATE TABLE Module
(
ModuleId INT NOT NULL IDENTITY(1,1)
CONSTRAINT PK_Module PRIMARY KEY CLUSTERED,
ModuleName VARCHAR(100)
)
CREATE TABLE CompoundModule
(
CompoundModuleId INT NOT NULL
CONSTRAINT FK_CompoundModule_MainModule
FOREIGN KEY REFERENCES dbo.Module(ModuleId),
BaseModuleId INT NOT NULL
CONSTRAINT FK_CompoundModule_BaseModules
FOREIGN KEY REFERENCES dbo.Module(ModuleId),
CONSTRAINT PK_CompoundModule
PRIMARY KEY CLUSTERED(CompoundModuleId, BaseModuleId)
)
and I filled in a few base modules:
INSERT INTO dbo.Module (ModuleName)
VALUES ('Base Module #1'), ('Base Module #2'), ('Base Module #3')
Now I created an EF 6 "code-first, reverse-engineer from database" model and get this Module class:
[Table("Module")]
public partial class Module
{
public Module()
{
Module1 = new HashSet<Module>();
Module2 = new HashSet<Module>();
}
public int ModuleId { get; set; }
public string ModuleName { get; set; }
public virtual ICollection<Module> Module1 { get; set; }
public virtual ICollection<Module> Module2 { get; set; }
}
and this context class:
public partial class ModuleCtx : DbContext
{
public ModuleCtx() : base("name=ModuleCtx")
{ }
public virtual DbSet<Module> Module { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Module>()
.Property(e => e.ModuleName)
.IsUnicode(false);
modelBuilder.Entity<Module>()
.HasMany(e => e.Module1)
.WithMany(e => e.Module2)
.Map(m => m.ToTable("CompoundModule").MapLeftKey("BaseModuleId").MapRightKey("CompoundModuleId"));
}
}
When I'm now trying to create a new compound module with this code, it turns out things aren't quite as easy as I thought.....
using (ModuleCtx ctx = new ModuleCtx())
{
Module newCompound = new Module();
Module baseModule1 = ctx.Module.FirstOrDefault(m => m.ModuleId == 1);
Module baseModule3 = ctx.Module.FirstOrDefault(m => m.ModuleId == 3);
newCompound.BaseModules.Add(baseModule1);
newCompound.BaseModules.Add(baseModule3);
ctx.Module.Add(newCompound);
ctx.SaveChanges();
}
This code causes an error (on the line trying to fetch the base module #1):
System.Data.Entity.Core.EntityCommandExecutionException was unhandled
HResult=-2146232004
Message=An error occurred while executing the command definition. See the inner exception for details.
Source=EntityFramework
InnerException: System.Data.SqlClient.SqlException
HResult=-2146232060
Message=Invalid column name 'Module_ModuleId'.
What am I missing here?? And why isn't the EF6 reverse-engineering code smart enough to create a model that works in this case??
I've been using EF4 with database-first approach so far, so all this fluent code-first configuration is still a bit of a mystery (and problem) to me...... does anyone see my (most likely very) obvious rookie mistake??
PS: this is the code that the "Code-first from existing database" reverse-engineering produces - not my own. So why does the reverse engineering output code that doesn't work in the end??
Try my generator EntityFramework Reverse POCO Generator and see if that does a better job for you.
It generated the following code (interesting stuff at the bottom):
public interface IMyDbContext : System.IDisposable
{
System.Data.Entity.DbSet<Module> Modules { get; set; } // Module
int SaveChanges();
System.Threading.Tasks.Task<int> SaveChangesAsync();
System.Threading.Tasks.Task<int> SaveChangesAsync(System.Threading.CancellationToken cancellationToken);
}
public class MyDbContext : System.Data.Entity.DbContext, IMyDbContext
{
public System.Data.Entity.DbSet<Module> Modules { get; set; } // Module
static MyDbContext()
{
System.Data.Entity.Database.SetInitializer<MyDbContext>(null);
}
public MyDbContext()
: base("Name=MyDbContext")
{
}
public MyDbContext(string connectionString)
: base(connectionString)
{
}
public MyDbContext(string connectionString, System.Data.Entity.Infrastructure.DbCompiledModel model)
: base(connectionString, model)
{
}
public MyDbContext(System.Data.Common.DbConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection, contextOwnsConnection)
{
}
public MyDbContext(System.Data.Common.DbConnection existingConnection, System.Data.Entity.Infrastructure.DbCompiledModel model, bool contextOwnsConnection)
: base(existingConnection, model, contextOwnsConnection)
{
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
}
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new ModuleConfiguration());
}
public static System.Data.Entity.DbModelBuilder CreateModel(System.Data.Entity.DbModelBuilder modelBuilder, string schema)
{
modelBuilder.Configurations.Add(new ModuleConfiguration(schema));
return modelBuilder;
}
}
public class Module
{
public int ModuleId { get; set; } // ModuleId (Primary key)
public string ModuleName { get; set; } // ModuleName (length: 100)
// Reverse navigation
public virtual System.Collections.Generic.ICollection<Module> BaseModule { get; set; } // Many to many mapping
public virtual System.Collections.Generic.ICollection<Module> CompoundModule { get; set; } // Many to many mapping
public Module()
{
BaseModule = new System.Collections.Generic.List<Module>();
CompoundModule = new System.Collections.Generic.List<Module>();
}
}
// Module
public class ModuleConfiguration : System.Data.Entity.ModelConfiguration.EntityTypeConfiguration<Module>
{
public ModuleConfiguration()
: this("dbo")
{
}
public ModuleConfiguration(string schema)
{
ToTable("Module", schema);
HasKey(x => x.ModuleId);
Property(x => x.ModuleId).HasColumnName(#"ModuleId").IsRequired().HasColumnType("int").HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);
Property(x => x.ModuleName).HasColumnName(#"ModuleName").IsOptional().IsUnicode(false).HasColumnType("varchar").HasMaxLength(100);
HasMany(t => t.CompoundModule).WithMany(t => t.BaseModule).Map(m =>
{
m.ToTable("CompoundModule", "dbo");
m.MapLeftKey("BaseModuleId");
m.MapRightKey("CompoundModuleId");
});
}
}

Table name in data annotations in entity framework doesn't work.

I create a project in MVC 5 with entity framework 6. I am using code first approach. I want in one of the models define a different name for the table then the default. For that I use the System.ComponentModel.DataAnnotationsname space and define the class like this:
[Table(Name="Auditoria")]
public class AuditoriaDAL
{
[Key]
public int AuditoriaId { get; set; }
...
}
Running the project I get a database with a table with the name AuditoriaDALs. Why the table have this name a not the name that I define?
You are referencing the System.Data.Linq.Mapping.Table attribute when you need to reference System.ComponentModel.DataAnnotations.Schema.Table. So either do this:
[System.ComponentModel.DataAnnotations.Schema.Table("Auditoria")]
public class AuditoriaDAL
{
[Key]
public int AuditoriaId { get; set; }
...
}
Or better yet:
using System.ComponentModel.DataAnnotations.Schema;
...
[Table("Auditoria")]
public class AuditoriaDAL
{
[Key]
public int AuditoriaId { get; set; }
...
}
https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations(v=vs.110).aspx
you can set TableName like below :
public class MyContext : DBContext
{
public virtual DbSet<AuditoriaDAL> Auditorias { get; set; }
}
Or in OnModelCreating :
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<AuditoriaDAL>().ToTable("Auditorias");
}
The name= isn't necessary. You should try [Table("Auditoria")].

Using Var on a DbSet inside a Dbcontext , will it be treated as IEnumerable OR as IQueryable

I am working on an asp.net mvc-4 web project, using database first approach. Now I have the following Context class:-
Public partial class IT360servicedeskEntities : DbContext
{
public IT360servicedeskEntities()
: base("name=IT360servicedeskEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public DbSet<TAccount> TAccounts { get; set; }
public DbSet<TAccountStatu> TAccountStatus { get; set; }
public DbSet<TContactInfo> TContactInfoes { get; set; }
public DbSet<TGroup> TGroups { get; set; }
public DbSet<TLogin> TLogins { get; set; }
public DbSet<TOrganization> TOrganizations { get; set
; }
Now let say inside my model class I wrote the following:-
var test = context. TOrganizations;
var2 = test.Where(a=>a.id == 100);
So my question what will be the var type ? will it be treated as IEnumerable OR as IQueryable, in other words will my above code cause the Where clause to be performed inside the memory or inside the database ?
Thanks
When you call the var t = test.Where(a=>a.id == 100) it will return IQueryable<TOrganization>. In you case, the Where is IQueryable's extension method, call this method will operate the Expression tree but no cause to be performed inside the database. When you foreach the t or call the t.ToList()/t.ToArray() it will visit Expression tree and build sql string, then get data from database.

How to set an attribute in a model that doesn't belong to the database

Inside of my model I have an attribute called attributes that its value is taken from the cutomized_attributes in my Database the property attributes does Not exist in the Database its just calculated value, while I'm trying to do the following I'm facing this error:
Error: System.Data.Entity.Edm.EdmEntityType: : EntityType 'JToken' has no key defined. Define the key for this EntityType
Model:
public class Restaurant
{
public int id{ get; set; }
public string name{ get; set; }
public string cutomized_attributes { get; set; }
private JObject _attributes { get; set; }
public JObject attributes
{
get
{
if (this._attributes == null)
return this._attributes = RestaurantAttributes.parseAttrString(this.cutomized_attributes);
return this._attributes;
}
set
{
this._attributes = value;
}
}
}
assuming you are using code first... within the dbcontext subclass
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Restaurant>().Ignore(x => x.attributes);
}

Entity Framework added s to my .dbo

I using "Entity Framework DbContext" at the moment I have got exception towars.dbo was not found. This is very strange because in my website I all the time ask about towar.dbo but no towars.dbo Do you know where is a problem?
- InnerException {"Invalid object name 'dbo.Towars'."} System.Exception {System.Data.SqlClient.SqlException}
My all things about Towar (of course different place in my program):
public class ProductController : Controller
{
//
// GET: /Product/
public ITowarRepository repository;
public ProductController(ITowarRepository productRepository)
{
repository = productRepository;
}
public ViewResult List()
{
return View(repository.Towar);
}
}
public interface ITowarRepository
{
IQueryable<Towar> Towar { get; }
}
public DbSet<Towar> Towar { get; set; }
public class EFTowarRepository : ITowarRepository
{
public EFDbContext context = new EFDbContext();
public IQueryable<Towar> Towar
{
get { return context.Towar; }
}
}
public class Towar
{
[Key]
public int Id_tow { get; set; }
public string Nazwa { get; set; }
public string Opis { get; set; }
public decimal Cena { get; set; }
public int Id_kat { get; set; }
}
Add the following line to your context:
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
You can tell EF to map to the table Towar by overriding the OnModelCreating method in your DBContext class with fluent API like this:
public class EFDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Towar>().ToTable("Towar");
}
}
Now EF will look for Towar table instead of Towars. If you do not have these tables created, there is some other problem you are having.
EF Code First automatically pluralizes the table names. Use a [Table] attribute to explicitly map the entity to a table name:
[Table("Towary")]
public class Towary
{
// Whatever properties
}
It looks like there's a way to disable pluralization gobally too, see Entity Framework Code First naming conventions - back to plural table names?.
using System.Data.Entity.ModelConfiguration.Conventions;
namespace MVCDemo.Models
{
public class EmployeeContext : DbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
For the sake of completeness #forty-two

Resources