Using OData with model inheritance cause missing property error - entity-framework

I got this error in my OData with asp.net core implementation during the runtime :The EDM instance of type '[XXX.Asset Nullable=True]' is missing the property 'externalId'.
The problem appear when I try to access the odata endpoint with the expand query: "/odata/v1/precinct?$expand=assets". It seems happening because I put the "ExternalId" property in my base class, its not happening if I put that property in the "Asset".
Below is my recent codes:
public abstract class Entity
{
public int Id { get; set; }
public string ExternalId { get; set; }
}
public class Precinct : Entity
{
public string Name { get; set; }
public string Description { get; set; }
public virtual IEnumerable<Asset> Assets { get; set; }
}
public class Asset : Entity
{
public string Name { get; set; }
public string Description { get; set; }
}
and here is my model configuration for ODATA
public class AssetModelConfiguration : IModelConfiguration
{
public void Apply(ODataModelBuilder builder, ApiVersion apiVersion)
{
var org = builder.EntitySet<Asset>("asset").EntityType;
org.HasKey(x => x.ExternalId);
org.Ignore(x => x.Id);
}
}
The strange thing is if I put that ExternalId in "Asset" class, it is working. Id property is the primary key while the "ExternalId" is marked as AlternateKey in the DBModel configuration.
am I missing something in my odata configuration? already tried many things but couldn't find a good answer. Any help would be appreciated!

Related

The entity type required a primary key to be defined - but there is

I probably have a fairly trivial problem with EF configuring 1 table. This is how my class looks like:
public class Task
{
[Key]
public int Id { get; set; }
[Required]
public string Description { get; set; }
[Display(Name = "Modification Date")]
public DateTime ModificationDate { get; set; }
[Required]
public bool IsDone { get; set; }
}
This is how dbContext looks like:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions options) : base (options) { }
public DbSet<Task> Tasks { get; set; }
}
And while creating migration I get this error:
The entity type 'Task' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating' [...]
But as you can see I have an attribute [Key], the property is public and has a setter, what could be the problem?
Ok, that was the dumbest mistake in a long time. It turned out the context was using the Task system class instead of my model class...

Entity Framework Core 2.0 - Error Migration "Field of entity type is readonly and so cannot be set"

There might be something wrong in my model that I cannot figure out since I get the following error when trying to make a migration:
"An error occurred while calling method 'BuildWebHost' on class Program. Continuing without the application service provider. Error: Field 'k__BackingField' of entity type 'MapeoArticuloProveedor' is readonly and so cannot be set.
Unable to create an object of type 'NSideoContext'. Add an implementation of 'IDesignTimeDbContextFactory' to the project, or see https://go.microsoft.com/fwlink/?linkid=851728 for additional patterns supported at design time."
Entities:
[Table("MapeosArticuloProveedor", Schema = "public")]
public class MapeoArticuloProveedor
{
public string Codigo { get; set; }
public int? IdLadoDeMontaje { get; set; }
[ForeignKey("IdLadoDeMontaje")]
public virtual LadoDeMontajeMapeoArticulo LadoDeMontaje { get; }
}
[Table("LadosDeMontajeMapeosArticulos", Schema = "public")]
public class LadoDeMontajeMapeoArticulo
{
public string Codigo { get; set; }
public string Valor { get; set; }
}
What could it be?
#WanneBDeveloper basically you're exposing the property since you made it public. A more conservative approach would be to set it as follows:
public LadoDeMontajeMapeoArticulo LadoDeMontaje { get; private set; }
note the private keyword
Then the propery can only be set from within the class and not outside of it. Therefore you'll know which class is mutating it's state.
this is your issue:
public virtual LadoDeMontajeMapeoArticulo LadoDeMontaje { get; }
Basically the error is saying you can't set the "LadoDeMontaje" once it is retrieved.
Simply change it to:
public virtual LadoDeMontajeMapeoArticulo LadoDeMontaje { get; set; }

How to configure Domain Classes to use ObservableCollection using EF?

I have started using Entity Framework Code First modeling technique and have seen many examples of implementing one to many (1-N) relationship using DataAnnotation and FluentAPI but all examples are using ICollection while modeling domain classes. I have already used generic ObservableCollection in my domain classes and do not intent to change it.
Currently while specifying the configuration using FluentAPI, i am getting following error:
HasRequired(t => t.App)
.WithMany(t => t.EndPoints) // error here
.HasForeignKey(t => t.App);
Cannot implicitly convert Type 'EndPoints' to 'ICollection'.
Note: EndPoints class is implemented using ObservableCollection.
My question is how to make it work?
Following is my entity definition:
public class ModelBase
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class RuleApp : ModelBase
{
public EndPoints EndPoints { get; set; }
}
public class EndPoint : ModelBase
{
public RuleApp RuleApp { get; set; }
}
public class EndPoints : GenericObservableCollection<EndPoint> { }
public class GenericObservableCollection<T> : ObservableCollection<T>
{
// other common stuff handling
}
This is an Example to do that :
public class ModelBase
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public class RuleApp : ModelBase
{
//This for create RelationShip
public virtual ICollection<EndPoint> EndPoints { get; set; }
[NotMapped]
Public EndPoints GenericEndPoints { get; set; }
public void TransferToGenric()
{
GenericEndPoints =new EndPoints(EndPoints)
}
}
public class EndPoint : ModelBase
{
public RuleApp RuleApp { get; set; }
}
public class EndPoints : GenericObservableCollection<EndPoint> { }
public class GenericObservableCollection<T> : ObservableCollection<T>
{
// other common stuff handling
}
If you use GenericObservableCollection as a Property EF Mapped all property in your calss, so I create just a property to use endpoint and after that i transform it to the GenericObserveableCollection.
in the constractor of you EndPoins class you have to featch all data in endpoint to do what you want

Breeze - self referencing entity

i get some problem using Breeze to execute queries via my ASP.NET web api application.
Here is my entity definition that i want to request on :
[Serializable]
[DataContract]
public class Subject
{
public Subject()
{
Subjects = new List<Subject>();
}
[DataMember]
public int Id { get; set; }
[DataMember]
public String Name { get; set; }
[DataMember]
public Subject Parent { get; set; }
[DataMember]
public IList<Subject> Subjects { get; set; }
}
and here is the query in my datacontext.js file
var query = EntityQuery.from("Subjects");
manager.executeQuery(query)
.then(function (data) {
// do something with data.results
})
.fail(function (error) {
});
but the query always fails with an error saying "expected object"
All other queries on other "simple" entities works fine.
If i remove the properties "Parent" and "Subjects" from my Subject Entity,
the query works.
Does anyone have an idea ?
Thanks !
Breeze needs a foreign key in order to fix up the relations between entities and you're missing it in your Subject class definition:
[DataMember]
public System.Nullable<int> ParentId { get; set; }
Or, if you are using non-conventional naming, be sure to add the ForeignKey tag to the navigation:
[DataMember]
[ForeignKey("FKParentId")]
public Subject Parent { get; set; }
You could also define it via Fluent Interface. You will find more on that at http://msdn.microsoft.com/en-us/data/hh134698.aspx.
Thanks !
i added :
[DataMember]
public System.Nullable<int> ParentId { get; set; }
and it works fine now.

Passing Generic Class' Property to ColumnAttribute in Code First Migration

I have an abstract class inherited in 3 POCO objects:
public abstract class BaseObject
{
public virtual int Id { get; set; }
}
public class Post : BaseObject
{
public string Name { get; set; }
public virtual ICollection<PostCategory> PostCategory { get; set; }
}
public class Category : BaseObject
{
public string Name { get; set; }
public virtual ICollection<PostCategory> PostCategory { get; set; }
}
public class PostCategory
{
[Key]
[Column("Id", Order = 0)]
public int PostId { get; set; }
[Key]
[Column("Id", Order = 1)]
public int CategoryId { get; set; }
public string Value { get; set; }
public virtual Post Post { get; set; }
public virtual Category Category { get; set; }
}
However, whenever I do 'add-migration' in Package Manager Console, I get error:
Schema specified is not valid. Errors: (30,6) : error 0019: Each
property name in a type must be unique. Property name 'Id' was already
defined.
Basically complaining the ColumnAttribute having same property name (Id property in PostCategory object).
I need the property name to be the same for creating generic class that is used in generic Repo class. That's why I have the Id in an abstract class. But, this gives me error on CF migration part. Is there a way to get around this?
Thanks!
The ColumnAttribute attribute, sets the name generated in the SQL server. Obviously the column Id cannot be generated twice.
Simply remove the ColumnAttributes, allowing the server to generate the PostCategory table peacefully.