I am facing a scenario in which I need to prevent direct creation of entity objects.
I am using Code First. I would like to have a method somewhere only using which I should be able to create the object. Is there any commonly used practice for this?
EF can work with entities having private/protected constructors.
So lets take this sample context:
public class MyEntity
{
protected MyEntity() { }
public int Id { get; set; }
public string Name { get; set; }
}
public class MyContext : DbContext
{
public DbSet<MyEntity> MyEntities { get; set; }
}
Then creating an entity with new MyEntity() will result in compilation error.
But you can still create entites through EF with DbSet.Create myContext.MyEntities.Create(); and all other operations on MyEntity will work e.g. queries and updates etc as expected.
And of course you can also have a static factory method on MyEntity which manages the object creation
public class MyEntity
{
//...
public static MyEntity MyCreate()
{
return new MyEntity();
}
}
Related
Is this the correct way I can get linked tables using where or is there another way to return the data.
GetMethod
public IEnumerable<Model.MeetingPollingQuestion> GetMeetingPollingQuestion(int MeetingPollingId)
{
using (var db = new NccnEcommerceEntities())
{
using (DbContextTransaction dbTran = db.Database.BeginTransaction())
{
var ListOfMeetingPollingQuestions = (from mpq in db.MeetingPollingQuestions
where (mpq.MeetingPollingId == MeetingPollingId)
select new Model.MeetingPollingQuestion
{
MeetingPollingId = mpq.MeetingPollingId.Value,
MeetingPollingQuestionType = mpq.MeetingPollingQuestionType,
MeetingPollingParts = (from mp in db.MeetingPollingParts
where mp.MeetingPollingPartsId == mpq.MeetingPollingId
select new Model.MeetingPollingParts
{
Type= mp.Type
}).ToList(),
}).ToList();
return ListOfMeetingPollingQuestions;
}
}
}
EF Model
namespace Repository.EFModel
{
using System;
using System.Collections.Generic;
public partial class MeetingPolling
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public MeetingPolling()
{
this.MeetingPollingQuestions = new HashSet<MeetingPollingQuestion>();
}
public int MeetingPollingId { get; set; }
public Nullable<int> MeetingId { get; set; }
public Nullable<System.DateTime> StartDate { get; set; }
public Nullable<System.DateTime> EndDate { get; set; }
public string PollingTitle { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<MeetingPollingQuestion> MeetingPollingQuestions { get; set; }
}
}
namespace Repository.EFModel
{
using System;
using System.Collections.Generic;
public partial class MeetingPollingQuestion
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public MeetingPollingQuestion()
{
this.MeetingPollingParts = new HashSet<MeetingPollingPart>();
}
public int MeetingPollingQuestionId { get; set; }
public string MeetingPollingQuestionType { get; set; }
public Nullable<int> MeetingPollingId { get; set; }
public Nullable<int> SequenceOrder { get; set; }
public virtual MeetingPolling MeetingPolling { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<MeetingPollingPart> MeetingPollingParts { get; set; }
}
}
namespace Repository.EFModel
{
using System;
using System.Collections.Generic;
public partial class MeetingPollingPart
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public MeetingPollingPart()
{
this.MeetingPollingPartsValues = new HashSet<MeetingPollingPartsValue>();
}
public int MeetingPollingPartsId { get; set; }
public string Type { get; set; }
public Nullable<int> MeetingPollingQuestionId { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<MeetingPollingPartsValue> MeetingPollingPartsValues { get; set; }
public virtual MeetingPollingQuestion MeetingPollingQuestion { get; set; }
}
}
Your entities have navigation properties for the related entities, so if you want to return entities and their relatives, just eager load the related entities using Include.
public IEnumerable<Model.MeetingPollingQuestion> GetMeetingPollingQuestion(int MeetingPollingId)
{
using (var db = new NccnEcommerceEntities())
{
var questions = db.MeetingPollingQuestions
.AsNoTracking()
.Include(mpq => mpq.MeetingPollingType)
.Include(mpq => mpq.MeetingPollingParts)
.Where(mpq => mpq.MeetingPollingId == MeetingPollingId)
.ToList();
return questions;
}
}
... and that's it. The important details here is the use of Include to eager load related data, and the use of AsNoTracking to ensure that the loaded entities are not tracked by the DbContext. These will be detached entities, copies of the data but otherwise not tracking changes or an association with a DbContext. These are suitable for read-only access to the data they contain.
Whenever returning "entities" outside of the scope of a DbContext you should ensure that they are non-tracked or detached. This is to avoid errors that can come up with potential lazy load scenarios complaining about that an associated DbContext has been disposed, or errors about references being tracked by another DbContext if you try associating these entities to a new DbContext. Your code performing a Select with a new class instance does the same thing, just more code.
Personally I do not recommend working with detached entities such as ever returning entities outside of the scope of the DbContext that they were read from. Especially if you decide you only need a subset of data that the entity ultimately can provide. Entities reflect the data state, and should always be considered as Complete, or Complete-able. (i.e. Lazy loading enabled) If the code base has some code that works with tracked entities within the scope of a DbContext, vs. detached entities, vs. copies of entity classes that might be partially filled or deserialized, it makes for buggy, unreliable, and un-reusable code. Take a utility method that accepts a MeetingPollingQuestion as a parameter. As far as that method is concerned it should always get a complete MeetingPollingQuestion. The behaviour of this method could change depending on whether it was given a tracked vs. detached, vs. partially filled in copy of a MeetingPollingQuestion class. Methods like this would need to inspect the entity being passed in, and how reliable can that logic be for determining why a related entity/collection might be missing or #null?
If you need to pass entity data outside the scope of the DbContext where you cannot count on that data being complete or related data being lazy loaded as a last resort, then I recommend using POCO DTOs or ViewModels for those detached or partial representations of the data state. With a separate POCO (Populated by Select or Automapper) there is no confusion between that representation and a tracked Entity.
Is it possible to inherit a custom DBContext and then modify the entities of the inherited context has without modifying the base tables with discriminator columns?
public class BaseDbContext: DbContext {
public IDbSet<BaseClass> BaseClasses { get; set; }
}
public class BaseClass {
public int Id { get; set; }
etc...
}
public class NewDbContext: BaseDbContext {
public IDbSet<NewBaseClass> NewBaseClasses { get; set; }
}
public class NewBaseClass: BaseClass {
public string SomePropertyName { get; set; }
}
I have a project that is setup for a base database structure use the BaseDbContext. If I created a new database with the same schema and added a column to the BaseClasses table called SomePropertyName. I want to create a new DbContext that derives from the BaseDbContext, and then add the extra property to the new class, NewBaseClass.
Any guidance would be greatly appreciated.
I want to use Table Per Concrete Class as the inheritance strategy for my XAF Code First EF project.
I use the wizard to create the project and then paste in classes from the following
namespace Solution12.Module.BusinessObjects {
public abstract class BaseBO // abstract class helpful in getting TPC
{
[Key]
public int Id { get; set; }
public string Description { get; set; }
}
[NavigationItem("People")]
[Table("People")] // explicit table name is helpful in preventing TPH
public class Person : BaseBO
{
public string PersonName { get; set; }
}
[NavigationItem("Organisation")]
[Table("Organisations")]
public class Organisation : BaseBO
{
public string OrganisationName { get; set; }
}
public class Solution12DbContext : DbContext {
...
public DbSet<Organisation> Organisations{ get; set; }
public DbSet<Person> People { get; set; }
//public DbSet<BaseBO> baseBOs { get; set; } // having this will cause TPT instead of TPC
}
}
This all works as I want, to create the database structure.
However I cant see the abstract class in the model designer at design time.
I can see the abstract class and it's views in the model designer at run time.
How can I get the model designer to show the abstract class BaseBO at design time?
This is a significant issue for us because run-time customizations are stored in the database and hence not part of our source control.
A ticket for this problem can also be found at Dev Express Support here however this is a more concise statement of what we now understand to be the problem.
It seems that if we pop the following into each concrete class then we get the desired behavior
[NotMapped]
public BaseBO BaseBo {
get
{
return (BaseBO)this;
}
}
I created WCF service that returned a collection of product entities from an entity frame work model .that product has self-reference .I consume data from WCF service in silverlight application .
i use Asynchronous methods . product entity was modeled this form of:
Public partial class Product
{
Public Product(){
this.product_11=new HashSet<Product>;
}
[DataMember]
public int Id{get; set;}
[DataMember]
public Nullable<int> subPro{get; set;}
[DataMember]
Public virtual Icollection<Product> product_11{get; set;}
[DataMember]
Public virtual Product product_12{get; set;}
}
and i use that in service methode
productEntity ef=new productEntity();
[OperationContract]
Public IEnumerable<Product> Getproduct()
{
return ef.Product;
}
in run time whene call service methode i get Time out error
"the HTTP request has ... exceeded the allotted timeout"
I think the problem lies in the usage of IQueryable as the return type in combination with WCF services.
[OperationContract]
Public IEnumerable<Product> Getproduct()
{
return ef.Product.ToList();
}
In this case query is executed with the call of the ToList() method, thus the WCF has not to execute the IQueryable.
The second part is that you might run into serialization problems, when returning objects of the model from your context. Because EF injects the feature for lazy loading into your model classes by inheritance.
You should switch off lazy loading for your current context in the service method:
context.ContextOptions.LazyLoadingEnabled = false;
context.ContextOptions.ProxyCreationEnabled = false;
This is described in this link
The next thing is that the serializer, which translates the model classes into XML-message has troubles with circular references. Here is an example which could lead to a problem:
public class A
{
public string PropA { get; set; }
public virtual B PropB { get; set; }
}
public class B
{
public string PropC { get; set; }
public virtual A PropD { get; set; }
}
You can avoid this by using the CyclicReferencesAware attribute for the OperationContractmethod:
[OperationContract]
[CyclicReferencesAware(true)]
Public IEnumerable<Product> Getproduct()
{
return ef.Product.ToList();
}
Hope this helps you!
Is there a way to tamper with the DbContext in order to auto eager load a specific Navigation property when the entity is requested in a query? (no lazy loading).
Entity Framework 5
Example:
var supremeEmployee = context.Employees.FirstOrDefault(x => x.EmployeeId == 42);
and the returned model would come back pre-populated with the "Department" navigation property.
Depends on what your model looks like. If you're using interfaces or inheritance you could add a function to your DbContext class with a generic constraint on that type that always includes the navigation property.
In my experience though you're usually better off not doing that, performance wise. I prefer to load into anonymous types just the fields i need in the moment.
In the most basic way you could do this:
public class Department
{
public int Id { get; set; }
}
public class Employee
{
public int Id { get; set; }
public Department Department { get; set; }
}
public class MyContext : DbContext
{
protected DbSet<Employee> Employees { get; set; }
public IQueryable<Employee> LoadEmployees()
{
return Employees.Include(p => p.Department);
}
}