Use virtual property in interface (EF) - entity-framework

How can I use a virtual property in an interface in Entity Framework?:
public interface ICommentable
{
int CommentableId { get; set; }
virtual ICollection<Comment> Comments { get; set; }
}
That throws an error for the virtual keyword, but if I do it this way:
public interface ICommentable
{
int CommentableId { get; set; }
ICollection<Comment> Comments { get; set; }
}
Then this (below) throws an error ("does not implement ...")
public class Something : ICommentable
{
int CommentableId { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
...more properties....
}

It throws an error because CommentableId is not public. It has nothing to do with placing virtual on Comments in the class which is valid.
Using virtual in interface is not valid because it doesn't make sense. When you define interface, the implementing class must implement all its members. Virtual keyword means that derived class can override existing implementation but the interface has no implementation.

Related

Maintaining a selected item from a colelction of items in Entity Framework (Code First)

This is my first question so hope
Basically given two classes like the following:
public class Teacher
{
public virtual Subject SelectedSubject { get; set; }
public virtual ICollection<Subject> Subject { get; set; }
}
public class Subject
{
public string SomeProperty { get; set; }
}
Ideally, I am trying to represent the fact that a teacher can have multiple subjects and is currently teaching a specific one.
The problem is despite setting the specific one (SelectedSubject), it always remains null. The virtual collection "subjects" loads fine though.
Can anyone help?
This seemed to work:
public class Teacher
{
[Key]
public int id { get; set; }
public virtual Subject SelectedSubject { get; set; }
public virtual ICollection<Subject> Subjects { get; set; }
}
public class Subject
{
[Key]
public int id { get; set; }
public string SomeProperty { get; set; }
}
and also:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Teacher>().HasMany(t => t.Subjects);
}

EF 4.3.1 Code First Sequence contains more than one matching element error

I've been getting this error in my project. Been stuck for a month now.
The problem is, I'm working on a enhancement of an existing project and the domain layer is really complex with more than 50 tables, so I'm unable to pinpoint the root cause.
The funny thing is, if the project where all the domain classes resides are within the main solution, the error occurs. But when I copy the project out and build it, copy the dll to the web application bin folder, it works without error. Exactly the same code. Other team members also do not experience this error.
Also, when I get the original source code before our development from TFS, the same error occurs. We have been able to do development without any error at least in 2 weeks in the beginning. So is it possible the SQL DB causing the error?
So I'm wondering if it's an EF bug. Any pointers to help me debug or find out the culprit domain class?
Here's the error screenshot.
http://imageshack.us/photo/my-images/10/8a1w.jpg/
--UPDATE--
The error is on the context.Database.Initialize when the web app is started.
Managed to find the entity causing the problem.
a. It's TPT + TPH
b. 2 tables having the same foreign key property name, in my example below, it's the WorkerBenefit property.
It's been reported here: http://entityframework.codeplex.com/workitem/677.
And it states Release: 6.0.0, means I have to use EF6?
[Table("Person")]
public abstract class Person
{
public int Id { get; set; }
public string PersonNumber { get; set; }
}
[Table("FullTimeWorker")]
public class FullTimeWorker : Person
{
public string FullTimeWorkerProperty { get; set; }
[ForeignKey("WorkerBenefit")]
public int WorkerBenefitId { get; set; }
[ForeignKey("WorkerBenefitId")]
public virtual WorkerBenefit WorkerBenefit { get; set; }
}
[Table("PartTimeWorker")]
public class PartTimeWorker : Person
{
public string PartTimeWorkerProperty { get; set; }
[ForeignKey("WorkerBenefit")]
public int WorkerBenefitId { get; set; }
[ForeignKey("WorkerBenefitId")]
public virtual WorkerBenefit WorkerBenefit { get; set; }
}
public class MorningShiftWorker : PartTimeWorker
{
public string MorningShiftWorkerProperty { get; set; }
}
public class EveningShiftWorker : PartTimeWorker
{
public string EveningShiftWorkerProperty { get; set; }
}
Maybe I might not fully understand your code, but instead of:
[Table("FullTimeWorker")]
public class FullTimeWorker : Person
{
public string FullTimeWorkerProperty { get; set; }
[ForeignKey("WorkerBenefit")]
public int WorkerBenefitId { get; set; }
[ForeignKey("WorkerBenefitId")]
public virtual WorkerBenefit WorkerBenefit { get; set; }
}
[Table("PartTimeWorker")]
public class PartTimeWorker : Person
{
public string PartTimeWorkerProperty { get; set; }
[ForeignKey("WorkerBenefit")]
public int WorkerBenefitId { get; set; }
[ForeignKey("WorkerBenefitId")]
public virtual WorkerBenefit WorkerBenefit { get; set; }
}
Shouldn't it be:
[Table("FullTimeWorker")]
public class FullTimeWorker : Person
{
public string FullTimeWorkerProperty { get; set; }
[ForeignKey("WorkerBenefit")]
public int WorkerBenefitId { get; set; }
public virtual WorkerBenefit WorkerBenefit { get; set; }
}
[Table("PartTimeWorker")]
public class PartTimeWorker : Person
{
public string PartTimeWorkerProperty { get; set; }
[ForeignKey("WorkerBenefit")]
public int WorkerBenefitId { get; set; }
public virtual WorkerBenefit WorkerBenefit { get; set; }
}
[Table("WorkerBenefit")]
public class WorkerBenefit : Person
{
public int WorkerBenefitId { get; set; }
public string benefit { get; set; }
}
This may help -- assuming the issue is related to the foreign keys like I think: How Should I Declare Foreign Key Relationships Using Code First Entity Framework (4.1) in MVC3?
If not, this is likely a problem with the models vs. the database. Had a similiar issue and, if you comment out the DbSets in your main database entity that point to these tables, then uncomment one by one, you'll find the one it's complaining about.

Additional virtual/navigation properties

I have the following model:
public class Useraccount
{
public int Id { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
}
The tasks collection is filled by the entity framework via the task entity. This is working without problems.
Now I'd like to have an additional virtual property so the class would look like this:
public class Useraccount
{
public int Id { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
public virtual ICollection<Task> FinishedTasks { get; set; }
}
The FinishedTasks property is the same like Tasks, but it only has tasks which are finished (which have the statusId = 1 for example).
Is it possible to do that with the EF? How?
Define the property like this:
public class Useraccount
{
public int Id { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
[NotMapped]
public IEnumerable<Task> FinishedTasks
{
get
{
return Tasks.Where(t => t.Finished);
}
}
}
NotMapped attribute tells the EF that this property is not mapped to a database column (see this page for more information).
There is no need to make it virtual (unless you exactly know why) because EF is not going to override it. Also the set accessor should not be present, because it is actually a calculated property.

Entity framework Database First & EF Code First get Relation Object By ID

in EF Database First when change ForeignKey(CommodityGroupID) automatic Get CommodityGroup for Commodity object, But in EF Code First(4.3.1) not doing.
public class Commodity
{
public int CommodityID { get; set; }
public string MadeBy { get; set; }
public decimal ServiceTimePrice { get; set; }
public decimal QCPrice { get; set; }
public int ServicePoint { get; set; }
public string Note { get; set; }
public int CommodityGroupID { get; set; }
[ForeignKey("CommodityGroupID")]
public virtual CommodityGroup CommodityGroup { get; set; }
}
public class CommodityGroup
{
public int CommodityGroupID { get; set; }
public string CommodityGroupName { get; set; }
public virtual ICollection<Commodity> Commodities { get; set; }
}
this Property defined in Edmx file (database first), i Should define this code in ef code first?
[BrowsableAttribute(false)]
[DataMemberAttribute()]
public EntityReference<CommodityGroup> CommodityGroupReference
{
get
{
return ((IEntityWithRelationships)this).RelationshipManager.GetRelatedReference<CommodityGroup>("GaamRepairModel.FK_Commodity_CommodityGroup", "CommodityGroup");
}
set
{
if ((value != null))
{
((IEntityWithRelationships)this).RelationshipManager.InitializeRelatedReference<CommodityGroup>("GaamRepairModel.FK_Commodity_CommodityGroup", "CommodityGroup", value);
}
}
}
It sounds like you're wanting a change tracking proxy. You want the CommodityGroup navigation property to update automatically when the FK is changed correct?
See this post on MSDN for details about the change tracking proxy.
This post on MSDN shows some code on how to test of your proxy object is being created properly.
Is this a new object? If so, you'll need to call the CreateObject function on your DbSet, not use the New Commodity().

MVVM subproperty change detection

My problem is as follows:
I am working with MVVM pattern and I would like to know how to detect changes of subproperties.
I have a textbox:
<TextBox Name="Descripcion" Text="{Binding AccionActual.Descripcion,Mode=TwoWay}" />
In the ViewModel I have the property:
Accion _accionActual;
public Accion AccionActual
{
get { return _accionActual; }
set
{
_accionActual = value;
RaisePropertyChanged("AccionActual");
}
}
The Accion entity definition is:
public partial class Accion : Entity
{
public Accion()
{
this.AccionesDocumentos = new HashSet<AccionDocumento>();
}
public int IdAccion { get; set; }
public int IdEmpleado { get; set; }
public string Descripcion { get; set; }
public string DescripcionDetalle { get; set; }
public bool Finalizada { get; set; }
public Nullable<int> IdExpediente { get; set; }
public Nullable<int> IdOrdenTrabajo { get; set; }
public bool Facturable { get; set; }
public Nullable<short> GestComAlbaranAƱo { get; set; }
public Nullable<short> GestComAlbaranEmpresa { get; set; }
public Nullable<int> GestComAlbaranNumero { get; set; }
public bool Facturado { get; set; }
public bool ComputarHorasACliente { get; set; }
public string DescripcionInterna { get; set; }
public virtual Aplicacion Aplicacione { get; set; }
public virtual AplicacionModulo AplicacionesModulo { get; set; }
public virtual Cliente Cliente { get; set; }
public virtual ClienteContacto ClientesContacto { get; set; }
public virtual Empleado Empleado { get; set; }
public virtual Expediente Expediente { get; set; }
public virtual OrdenTrabajo OrdenesTrabajo { get; set; }
public virtual ICollection<AccionDocumento> AccionesDocumentos { get; set; }
}
I could create in the ViewModel a property for each of the properties of Accion, but there any way to receive the changes without having to create a property for each of the properties of Accion?
You have two choices- either modify the Accion class to implement INotifyPropertyChanged or create a ViewModel wrapper to do it.
Where you put this is up to you- do what works best for you. There is a question on the merits of doing it in the ViewModel vs Model class here.
You could take out the manual process of doing this by looking into something like notifypropertyweaver- try using Google to look for INotifyPropertyChanged Aspect Oriented Programming. There is a Stackoverflow question on it here.
This kind of redundant double wrapping by the ViewModel is a common problem in classic MVVM and drives me nuts too.
You have several options:
Have your entity implement INotifyPropertyChanged and expose the Entity to the View the way you did it with the AccionActual property.
Hide your Entity completely behind a corresponding ViewModel object, and add only those properties to the ViewModel that you actually need in the View. Introduce a clever change notification infrastructure that notifies your ViewModel about changes in the Model and raise PropertyChanged in your ViewModel accordingly. This "change notifcation infrastructure" could be an EventAggregator and maybe you can get away with some sort of bulk/meta update (e.g. raise NotifyPropertyChanged for all relevant properties in the ViewModel when you received the event "the entity changed".