I am using database first approach. I already mapped my tables and have generated entities. In my edmx model I have changed table names so that my entity names are more readable. But now for some reason I need to get original table/column name for my entities. Is there anyway in which I can update tt file to get table/column names? (See desired code below).
// Current generated code for entity,
public partial class University
{
public int DepartmentCount { get; set; }
}
// Desired code for entity,
[Description("TABLE_UNIVERSITY")]
public partial class University
{
[Description("DEPARTMENT_COUNT")]
public int DepartmentCount { get; set; }
}
Related
Assuming this test model:
public class TestEntity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
When I generate a new instance of it, Id is 00000000-0000-0000-0000-000000000000.
Saving such an instance in the database as a new row, results in a Guid being generated (which is different from the empty one).
However, if I provide a valid Guid in TestEntity.Id, the new row is created with the provided Guid instead of a newly computed one.
I would like this behavior to exists only when editing a row, not when creating it. This is to ensure a database-layer protection from attacks where a user normally shouldn't get to choose which data to input.
Off course this protection is present in other layers, but I want it in the database too. Is this possible? How can I tell EF to ignore model data when creating a new row?
DatabaseGeneratedOption.Computed descriptions says
the database generates a value when a row is inserted or updated
So clearely that's not an option. I don't want to change Id when updating a row. I only want to be sure no one can create a row and choose the Id.
I'd try to keep things simple. Make your set method protected, then you have two ways to generate Ids, You can generate it by yourself inside a constructor:
public class TestEntity
{
// no need to decorate with `DatabasGenerated`, since it won't be generated by database...
[Key]
public Guid Id { get; protected set; }
public string Name { get; set; }
public TestEntity()
{
this.Id = Guid.NewGuid();
}
}
...or you can let the database generate it for you. At least for SQL Server, it will be able to generate for int and Guid as well:
public class TestEntity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Guid Id { get; protected set; }
public string Name { get; set; }
// no need to generate a Guid by yourself....
}
This will avoid people from setting a value to Id outside the class (therefore no one can choose a Guid for new rows, or modify from existing ones).
Of course, your team could use reflection to by-pass class definitions, but if that's the case, you need to have a talk with your team.
If you still want to make sure they won't cheat, then you'd have to do check before saving changes to database, maybe overriding SaveChanges() in your DbContext.
As a side note, for both int and Guid, values are not generated by Entity Framework. Decorating the property with [DatabaseGenerated(DatabaseGeneratedOption.Identity)] will tell Entity Framework to generate a column with a default value coming from the own database provider.
I'm using Entity Framework edmx. When I update the edmx I lose my metadata.How do you create and use metadata properties (that are not real fields).
Create a Metadata folder in the project where is the edmx. Create a class with the name of your entity as bellow: And within the same file create another class with the name of your entity with the "metadata" extension (MyEntityMetadata).
namespace MyNameSpace.DataAccess //You need to use the same namespace of edmx entities files
{
[MetadataType(typeof(MyEntityMetaData))]
public partial class MyEntity //This is possible because entities files using partial class
{
[NotMapped] //System.ComponentModel.DataAnnotations.Schema
public int MyProperty { get; set; }
//more properties...
}
public class UsuarioMetaData
{
[Display(ResourceType = typeof(Resources.Global), Name = "MyFieldLabel")]
public int MyField { get; set; }
//More fields
}
}
If I have the following code generating my database it assigns a foreign key from the TankComponent table to the Asset table instead of the Tank table. Can someone explain why? Do I need to turn off a specific convention or change in the Fluent API? Is it really only looking at the column name?
[Table("Asset")]
public abstract class Asset
{
[Key]
public int AssetId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
[Table("Tank")]
public class Tank : Asset
{
public Tank()
{
this.TankCompnents = new Collection<TankComponent>();
}
public int TankField1 { get; set; }
public ICollection<TankComponent> TankCompnents { get; set; }
[NotMapped]
public IEnumerable<Floor> Floors { get { return this.TankCompnents.OfType<Floor>(); } }
}
[Table("TankComponent")]
public abstract class TankComponent
{
[Key]
public int TankComponentId { get; set; }
[ForeignKey("Tank")]
public int AssetId { get; set; }
public Tank Tank { get; set; }
public string Name { get; set; }
}
//forgot this in initial post
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Tank>()
.Map(m =>
{
m.Properties(a => new { a.AssetId, a.Name, a.Description });
m.Requires("AssetType").HasValue(1);
m.ToTable("Asset");
})
.Map(m =>
{
m.Properties(t => new { t.AssetId, t.TankField1 });
m.ToTable("Tank");
});
}
This mapping line...
m.Requires("AssetType").HasValue(1);
...and your comments seem to indicate that you possibly have a misunderstanding how Table-Per-Type (TPT) inheritance works.
EF does not need a specific column in the table of the base class Asset to detect what the actual type of the entity with a given primary key value is - unless you would use Table-Per-Hierarchy (TPH) inheritance mapping (i.e. a mapping without having [Table] attributes on your entities). For TPH a specific column - the discriminator - in indeed necessary to distinguish between the types because all properties of all entities in the inheritance tree would be stored in a single table. If you don't specify a discriminator explicitly - like AssetType - EF would create a column called Discriminator by default.
Now, TPT is a different story. If you query an entity that has other derived entities - for example...
var asset = context.Assets.First();
...EF will not only create a SQL query like SELECT TOP(1) * FROM ASSETS on the base table alone but instead a - possibly very complex - query with many LEFT OUTER JOINs to many other tables that belong to all possible derived entities. This query would either find a row in the Tank table or not. If it does find one EF will materialize a Tank object. If not it will materialize an Asset. (Cannot be the case here because Asset is abstract but assume for a moment it would not be abstract.) If Asset has other derived types EF will join their tables as well and decide again about the concrete entity type depending on the existence of joined rows.
So, with TPT the type is detected not by a special column but only by the result of (left outer) table joins.
The line above seems to confuse EF somehow. But it really doesn't belong into a TPT mapping and I would remove your whole mapping with Fluent API.
I've tested that the result is correct when you remove the mapping - i.e. the FK relationship will be created between TankComponent and Tank table (not Asset table).
DB has a table PackagingInfo. I have a Package class, and a ShopEntities : DbContext.
// Entity (ex. Package.cs)
[Table("PackagingInfo")]
public class Package
{
public decimal PackageID { get; set; }
public decimal Title { get; set; }
public decimal Cost { get; set; }
public bool isFree { get; set; }
}
// Entity Context (ex. ShopEntities.cs)
public class ShopEntities : DbContext
{
public DbSet<Package> Packages { get; set; }
}
// Controller Action (ex. HomeController.cs)
public ActionResult Index()
{
ShopEntities _db = new ShopEntities();
var q = _db.Packages.ToList();
return View(q);
}
After instantiating the _db context and inspecting its Packages property and exception is noticed:
The entity type Package is not part of the model for the current context.
Update
I've edited this question and requested its reopening because the situation is also occuring in a Model first approach where the table mapping is done in the EDMX file instead of the annotation noticed here:
Model Browser window shows the Package in bot the Model and Store entity types, and the entity's Table Mapping shows each property properly mapped to the table column. This is the same mapping accomplished by the annotation code-first style.
Explicitly add the “DatabaseGenerated” attribute to set the “identity” value of the column in database
[DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]
Specify the precision for the decimal data type. This is because by default it assumes there are two numbers after the decimal for decimal data type. We need to set it 0.
modelBuilder.Entity<User>().Property(x => x.ID).HasPrecision(16, 0);
I am new to using the ADO.NET Entity Data Model tool. I have a table in my database that has three properties (FirstName, LastName, Age). I need to add a field to this entity called IsChosen. However, I cannot add this column in the database.
How do I add custom properties to entities generated through this tool?
Thank you!
The Entity Data Model tool creates partial classes.
You can extend those partial classes in another source file. You just need to make sure your section of the partial class lives in the same namespace as the Entity Data Model generated classes. For example:
Tool Generated Code
namespace Your.Generated.Classes
{
public partial class Stuff
{
public string Name {get; set;}
public int Age {get; set;}
}
}
Your Seperate Code File
namespace Your.Generated.Classes
{
public partial class Stuff
{
public string NonDatabaseProperty {get; set;}
}
}