The properties expression is not valid. The expression should represent a property - entity-framework-6

I have these two entities
public class Song : IPathHavingEntity
{
public int Id { get; set; }
[Required]
public string Path { get; set; }
[Required]
public virtual Album Album { get; set; }
[Required]
public int TrackNumber { get; set; }
}
public class Album : IPathHavingEntity
{
public int Id { get; set; }
[Required]
public string Path { get; set; }
public virtual IEnumerable<Song> Songs { get; set; }
[Required]
public int AlbumNumber { get; set; }
}
Path is defined in the IPathHavingEntity interface.
In my Seed method I want to add a song to the Songs table only if it doesn't exist. For this reason I check that the album path and song path combination don't exist already before adding it thus
context.Songs.AddOrUpdate(
s => new { FilePath = s.Path, AlbumPath = s.Album.Path },
new Song { TrackNumber = 1, Path = "01 Intro.mp3", Album = one });
The problem is I get this error
The properties expression 's => new <>f__AnonymousType0``2(FilePath =
s.Path, AlbumPath = s.Album.Path)' is not valid. The expression should
represent a property: C#: 't => t.MyProperty' VB.Net: 'Function(t) t.MyProperty'. When specifying multiple properties use an anonymous type: C#: 't => new { t.MyProperty1, t.MyProperty2 }' VB.Net: 'Function(t) New With { t.MyProperty1, t.MyProperty2 }'.
What's the problem?

In my case, The Only modification I did that on the Model Classes forget to put {get; set;} with the property declaration, Thus ...It's solved my problem.
Like this:
Before:
public int Supplier_ID;
public String Supplier_Code;
After:
public int Supplier_ID { get; set; }
public String Supplier_Code { get; set; }
Kindly Check your Model Classes should have the Get/Set property

I struggled with a similar issue for several hours today and was finally able to resolve it. I'm not sure if this will work for your situation but it's worth investigating.
The problem may be caused by the Album property of your Song entity being marked as virtual. I'm not an EF expert but I don't think it likes that virtual property when initializing your anonymous type. Add a non-virtual property for the album path (but keep the virtual navigation property), like this:
public class Song : IPathHavingEntity
{
public int Id { get; set; }
[Required]
public string Path { get; set; }
[Required]
public virtual Album Album { get; set; }
public string AlbumPath { get; set; }
[Required]
public int TrackNumber { get; set; }
}
And then perform the AddOrUpdate using that non-virtual property, like this:
context.Songs.AddOrUpdate(
s => new { FilePath = s.Path, AlbumPath = s.AlbumPath },
new Song { TrackNumber = 1, Path = "01 Intro.mp3", Album = one });
EF should then only allow you to add songs where the given song path and album path do not already exist. Whether your Song domain object can have a non-virtual AlbumPath property is another question but this should at least allow you to run your seed method in the way you described.

EF does not create a column for a property which does not have either getters or setters. For example, EF will not create columns for the following City and Age properties.
using System.ComponentModel.DataAnnotations;
public class Student
{
private int _age = 0;
public int StudentId { get; set; }
public string StudentName { get; set; }
public string City { get{ return StudentName;} }
public int Age { set{ _age = value;} }
}
Referance : https://www.entityframeworktutorial.net/code-first/notmapped-dataannotations-attribute-in-code-first.aspx

In my case, changing the following values in the mapper worked.
From:
this.HasKey(t => new { FirstName = t.FirstName, LastName = t.LastName });
To:
this.HasKey(t => new { t.FirstName, t.LastName });

What has not been mentioned in any of other answers is that the source of the problem in any case shown is the same: The "custom identification expression" passed in as a parameter of the AddOrUpdate method has to be a valid property of the entity being inserted or updated. Also, it will not accept ComplextType.Property there.
For example:
context.Songs.AddOrUpdate(
s => new { k.Path, k.AlbumPath },
new Song { TrackNumber = 1, Path = "01 Intro.mp3", Album = one });
Note that the problem was resolved when the AlbumPath was used and also note that the anonymous type requires no other fields to be created. Instead, you just need to specify the property names.
It worth mentioning to be careful when using AddOrUpdate as the result can be destructive.

Related

How can I query Entity Framework to a different class and get a count instead of a list property?

Let's take an example model:
public class Person
{
public string Name {get; set;}
public List<Guitar> Guitars {get; set;}
}
public class Guitar
{
public string Brand {get; set;}
public string Model {get; set;}
}
I need to create a View with a list of all People and a count of how many guitars they have. To do that I would like to pass a ViewModel like this one populated with EF without loading all Guitards:
// This will be send to the View, I can also just send a List
public class ViewModelPassed
{
List<PeopleGuitarViewModel> AllPeople { get; set; }
}
// This should be populated from EF
public class PeopleGuitarViewModel
{
public string Name { get; set; }
public int NumberOfGuitars { get; set; }
}
Can I query EF to a different class, and avoid bringing the whole list of guitars and instead get a COUNT in SQL?
Thanks!
You should provide primary key to your models for EF core to create the relationship:
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public List<Guitar> Guitars { get; set; }
}
public class Guitar
{
public int ID { get; set; }
public string Brand { get; set; }
public string Model { get; set; }
}
Also use public for AllPeople property in ViewModelPassed:
public List<PeopleGuitarViewModel> AllPeople { get; set; }
Then query like :
ViewModelPassed modelPassed = new ViewModelPassed();
modelPassed.AllPeople = new List<PeopleGuitarViewModel>();
modelPassed.AllPeople = _applicationDbContext.Persons.Select(x =>
new PeopleGuitarViewModel
{
Name = x.Name,
NumberOfGuitars = x.Guitars.Count
}).ToList();
One way is to do it like this:
var viewModel=context.Persons.Select(x=>new PeopleGuitarViewModel
{
Name=x.Name,
NumberOfGuitars=Guitars.Count()
}).ToList();
this kind of query is also named Projection and is consider best practice (do not send full entity to the view).
There are 2 libraries which I often use for such projections: AutoMapper and/or Mapster.
Hope this help you.
When populating your ViewModel, you can use Linq to get the count. Like this:
PeopleGuitarViewModel p= new PeopleGuitarViewModel();
p.Name = person.Name;
p.NumberOfGuitars = person.Guitars.Count;
Where person is an object of your Person class.

Constructor for object model similar from entity

I'm trying my best to follow some MVC guidelines and for now, I have created a model with the fields I need from an entity I have. I have created the following Model class:
public class PersonStyle
{
public string Name { get; set; }
public int? Age { get; set; }
public string City { get; set; }
public string Style { get; set; }
}
My Entity is sometihng like:
public class PersonOE
{
public string Name { get; set; }
public int? Age { get; set; }
public string City { get; set; }
}
Im trying to build a constructor for the following:
PersonON personBus = new personBus();
List<PersonStyle> personStyleList = new List<PersonStyle>(personBus.getPeople()); //getPeople(); returns a PersonOE list
For this all, I need suggestions on how to create the PersonStyle constructor that will put "null" into the only different variable from the PersonOE model.
All you need to do is use LINQ to generate your properties. Though, adding your Style to each of them could get a little harder to deal with, but you haven't given any input on where they're coming from. This is a quick and easy way to convert from your data to model objects.
List<PersonStyle> personStyleList = personBus.GetPeople()
.Select(p => new PersonStyle {
Name = p.Name,
Age = p.Age,
City = p.City
});

Initilialize Navigation Property when creating new Entity with Breeze

I have simple Model defined as
public class Project
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int StatusId { get; set; }
public virtual Status Status { get; set; }
}
public class Status
{
public int Id { get; set; }
public string Name { get; set; }
}
So, currently If I try to create a new Project Entity with breeze, it initializes the navigation property "Status" with null. How can I initialize it with default value? Note that, I don't want any binding with drop down field for this field at least for create operation.
function createNewProject() {
return manager.createEntity('Project');
}
You can define a custom constructor for the Project entity type and set a default StatusId value in there. The Status navigation property will be set to the relevant status entity (assuming the entity is in the breeze cache). For example:
function Project() {
this.StatusId = desiredDefaultStatusEntityId;
}
var manager = new breeze.EntityManager('...');
manager.metadataStore.registerEntityTypeCtor('Project', Project);
Take a look at Extending entities for some more information on extending entities.

Saving many to many relationship tables in Asp.Net MVC

I use Asp.Net MVC, Entity Framework. I have a form it looks like below.
Here, dropdownlist is filled from a table(types). Checkboxes is filled from another table(test). Tables are like below:
public class Types
{
public int TypesID{get;set;}
public string TestName { get; set; }
public string TestExplanation { get; set; }
public int TestTime { get; set; }
}
public class Tests
{
public int TestID{get;set;
public string Name { get; set; }
public string Code { get; set; }
}
public class Types_Tests
{
public int Types_TestsID{ get; set; }
public int TypesID { get; set; }
public int TestsID { get; set; }
public virtual Types Types { get; set; }
public virtual Tests Tests { get; set; }
}
Types_test table is relation table between Types and Tests. When I click Kaydet button, it shuld save type and checked tests. I made this operation using ViewBag, javascript and hdnvalue.I added checked checkboz values to a hdntext. I made saving process like below:
[HttpPost]
public ActionResult Index(string drpType, string hdntesttypes)
{
var TypeList = Types.GetAll();
ViewBag.TypesList = new SelectList(TypeList, "Id", "Name");
var testypeList = testTypes.GetAll();
ViewBag.TestTypesList = new SelectList(testypeList, "Id", "TestName");
GenericRepository<TestDisabledTypes> testDisabledRepository = new GenericRepository<TestDisabledTypes>(_context);
if (!string.IsNullOrEmpty(hdntesttypes))
{
string[] disabletypesArray = hdntesttypes.Split(',');
using (TransactionScope trns = new TransactionScope())
{
for (int i = 0; i < disabletypesArray.Length; i++)
{
Test_Types types = new Test_Types ();
types.TestTypesID = Convert.ToInt32(disabletypesArray[i]);
types.TypesID = Convert.ToInt32(drpType);
testDisabledRepository.Insert(types);
}
trns.Complete();
}
}
return View();
}
It wokrs. But I search better solution for this process. Can someone give me any idea?
Thanks.
If you don't need additional attributes for your entity class, you don't need create link table.
Just define the following class, and EF will generate the link table for you automatically.
public class Type
{
public int TypesID{get;set;}
public string TestName { get; set; }
public string TestExplanation { get; set; }
public int TestTime { get; set; }
public ICollection<Test> Tests { get; set; }
}
public class Test
{
public int TestID{get;set;
public string Name { get; set; }
public string Code { get; set; }
public ICollection<Type> Types {get;set;}
}
Well, in EntityFramework if you want to create a many to many relation object you need to create new object of "linking" entity. Unfortunately, it is not possible to add first object, add second object and say "Guys, you are in many to many relationships. Are you happy then?" :) You need to create relation object, set appropriate fields in it (I think these are ids of two objects itself) and add it to relation collection (entity) in your model. But before doing so you need to be sure that objects with data you are linking with are already exists in database. Otherwise you'll get an error
Also it's not necessary to create manually transaction because EF does it for you automatically each time you get/save your data

ASP.NET MVC 3 EF Code First - How do I make a model that optionally refers to a parent of its own type?

I'm trying to create a model that can optionally refer to a parent of the same type, for example:
public class Category
{
public virtual long CategoryID { get; set; }
public virtual Category? ParentCategory { get; set; }
public virtual int UserID { get; set; }
public virtual string Name { get; set; }
}
As you can see there is an optional member called ParentCategory that is optional and refers to a class of type Category (i.e. the same type). As I'm sure you can guess, I'm trying to create a simple Category tree, where the root node(s) will not have a parent.
This results in the following error when the Entity Framework tries to create the database:
"The ForeignKeyAttribute on property 'ParentCategoryID' on type 'MyProject.Models.Category' is not valid. The navigation property 'Category' was not found on the dependent type 'MyProject.Models.Category'. The Name value should be a valid navigation property name."
I also tried this:
public class Category
{
public virtual long CategoryID { get; set; }
[ForeignKey("Category")]
public virtual long? ParentCategoryID { get; set; }
public virtual int UserID { get; set; }
public virtual string Name { get; set; }
}
But again this resulted in the same error.
Is it possible to model this using EF Code First? Its easy to model it int he database if I were to create the database manually.
Thanks in advance
Ben
Your first example wouldn't even compile because T?, a shortcut for Nullable<T> can only be applied to value types.
The following works fine here:
public class Category
{
public virtual long CategoryID { get; set; }
public virtual Category ParentCategory { get; set; }
}
Now, this will use an ugly name by default for the FK, ParentCategory_CategoryID.
This is a way to get a nicer name, plus some flexibility when using it:
public class Category
{
public virtual long CategoryID { get; set; }
[ForeignKey("ParentCategoryID")]
public virtual Category ParentCategory { get; set; }
public virtual long? ParentCategoryID { get; set; }
}

Resources