How do you go about protecting the primary key property on a POCO object that is used by EF?
If I have a POCO like so:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
....
}
How do I prevent someone form changing the value of the Id?
EF uses reflection to set property values. Thus, even private setter will work:
public Id { get; private set; }
You could mark the setter as internal, that way only the containing assembly classes can modify it.
public class Customer
{
public int Id { get; internal set; }
public string FirstName { get; set; }
....
}
I'm not really sure what purpose you are using EntityFramework for, but keep in mind that if that field is getting serialized either for a web app or a service, users will still be able to modify that field. So when you are saving any object to your database, you should always verify that a user has the authority to edit that object.
Related
I made this basic example to illustrate what I'm talking about. Basically I want to automatically set the "HasEngine" property whenever an Engine is added to a Car. I believe the way to do this is to override the setter for either the Engine or the EngineId property of the Car class, but which one should it actually be done in? Or is there a better way to manage this kind of 'dependent' property?
public class Car
{
public bool HasEngine { get; private set; }
public int? EngineId { get; set; }
public Engine Engine { get; set; }
}
public class Engine
{
public int EngineId { get; set; }
public IList<Car> Cars { get; set; }
}
As far as EF Core goes I do want to store the HasEngine property in the database, I just don't want to have to set it manually every time
If you need the calculated value in reporting that's being done without the EF model, you can make HasEngine a calculated property in the database and a read-only property in EF.
Suppose that I need to have two tables named Wagons and WagonTypes. Obviously enough, each row in the Wagons table should reference to the correspoding WagonTypes record via foreign key.
Am I doing this right?
public class Wagons
{
public Guid Id { get; set; }
[Required]
public WagonTypes Type { get; set; }
}
public class WagonTypes
{
public Guid Id { get; set; }
[Required]
public string Name { get; set; }
}
Yeah, it works and all that but I don't unserstand why there's an additional field in the docs then:
public int BlogId { get; set; }
public Blog Blog { get; set; }
What's the point of having a BlogId field? Should I define it too?
You don't have to add the foreign key, but it's recommended because it makes your life easier.
Imagine you want to edit some row in table Wagons (for example property Name). You have to get the object, edit Name, then load property Type and then call SaveChanges. If you didn't load Type, EF would think you want to edit that Type too.
If you had public int TypeId{ get; set; } in your Wagons class, you could just get that object, directly edit Name and call SaveChanges without any further loading.
This is similar to questions here and here, but those are old and have no good answers.
Let's say I have the following classes:
class HairCutStyle {
public int ID { get; set; }
public string Name { get; set; }
}
class CustomerHairCutPreference {
public int ID { get; set; }
public Customer Customer { get; set; }
public HairCutStyle HairCutStyle { get; set; }
}
Let's say my HairCutStyle data is stored in a table in another database (I get it from Paul Mitchell himself). I want to use the HairCutStyle class as a POCO class - something that I will use in code to represent hair cut styles, but I don't need to read/write that information in my database. (Assume I have a separate service layer that can populate the data for these classes from the other database.)
How can I tell EF NOT to create a HairCutStyle table in my current db context? But at the same time, I want to store a value in the CustomerHairCutPreference table that is a reference to the HairCutStyle data stored elsewhere. A "virtual" foreign key of sorts, that isn't constrained by an actual database FK constraint.
Add a property in CustomerHairCutPreference for HairCutSytleID and then use the [NotMapped] attribute on the HairCutStyle property. Note, however, that you will then be responsible for ensuring that the HairCutStyle and HairCutStyleID stay in sync.
class CustomerHairCutPreference {
public int ID { get; set; }
public Customer Customer { get; set; }
public int HairCutStyleID {get; set; }
[NotMapped]
public HairCutStyle HairCutStyle { get; set; }
}
Alternatively, you can use the FluentAPI to exclude HairCutStyle completely from ever being mapped by Entity Framework, which may be useful if you have multiple classes that link to it.
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Ignore<HairCutStyle>();
}
There are three things to ensure:
Make sure you do not expose a DbSet<HairCutStyle> in your DbContext-derived class
Make sure you do not have any mention of HairCutStyle in your OnModelCreating override
Mark your HairCutStyle property using the NotMapped attribute.
I'm in the process of converting a project from NHibernate to Entity Framework 6.
Given this simple model:
public class User
{
public int ID { get; set; }
public string FullName { get; set; }
public virtual Organization Organization { get; set; }
// [...]
}
public class Organization
{
public int ID { get; set; }
public string Name { get; set; }
public virtual List<User> Users { get; set; }
// [...]
}
Accessing the primary key (ID) through the Organization navigation property will cause the whole Organization entity to be loaded into the context:
foreach(var user in db.Users)
Console.WriteLine(user.Organization.ID);
Given that the OrganizationID foreign key is part of the User row, I should be able to access it without causing a Lazy Load of the whole entity (and indeed, NHibernate does this properly).
Short of adding properties for the foreign key IDs into all of my 100+ entities so I can access their values without loading the entities, is there anything to be done to avoid this behaviour?
EDIT: Furthermore, even doing a null check will cause a load of the Organization entity (not in NHibernate):
foreach(var user in db.Users)
Console.WriteLine(user.Organization != null);
I guess this is due to the fundamental differences in the way the entity proxy is implemented in these two frameworks. So I'll have to adapt all of my code to this new frustrating behaviour... Unless someone already had to go through this and could enlighten me?
Nope, you'll need to add them as property in your class (that is; if you want it strong typed) like this to access it directly.
public class User
{
public int ID { get; set; }
public string FullName { get; set; }
//added ID
public int OrganizationID { get; set; }
public virtual Organization Organization { get; set; }
// [...]
}
By accessing the int you'll prevent the lazy loading, EF will bind the ID through naming conventions. Having said that: 100+ classes... :|
UPDATE:
As I just realized; you might want to try:
db.Users
.Include("Organization.ID")
.Where(/*your stuff*/) //etc.;
I am not certain if it will fully load the nested property. If it doesn't, it might be a small performance gain.
I have a model with some inherits and it is using nhibernate to persisti on a Database. The nhibernate mapping with fluent nhibernate is working fine, but I have a scenario where I need to save a child for a existent parent. My model looks like this:
public class Item
{
public long Id { get; set; }
public string Name { get; set; }
// other properties
}
public class ItemCommercial : Item
{
public decimal Value { get; set; }
// other properties
}
In my Database, the respective tables are related by Id <-> Id (one per one).
I would like to know, how to Save just a ItemCommercial instance for a existent Item on database. I have the Id of the Item, but I do not know howt to say to nhibernate to say just the Child, instead creating a new Item, for sample:
session.Save(itemCommercialObj); // will create a Item and ItemCommercial with the same Id
Thank you.
As I also answered here
No, it is not possible to "upgrade" an already persisted object to its subclass. Nhibernate simply doesn't support this.
If you safe the subclass with the same ID as the base class, Nhibernate simply creates a copy with a new ID of the object instead of creating the reference to Member...
So basically you could do either
Copy the data of Customer into Member, delete customer and save Member
Use a different object structure without subclasses where Member is a different table with it's own ID and a reference to Customer
Use native sql to insert the row into Member...
you can not the runtimetype of an object like that hence NH does not support it. Change the design to
public class Item
{
public long Id { get; set; }
public string Name { get; set; }
public CommercialValue CommercialValue { get; set; }
// other properties
}
public class CommercialValue
{
public Item Item { get; set; }
public decimal Value { get; set; }
// other properties
}
and a one-to-one mapping. Then it is as simple as setting the CommercialValue property