So I have a controller which updates just 2 fields in a db entry, however that entry is linked to two other tables, I know it's a bad explanation but sometimes it works and sometimes it doesn't and I cant identify what's different between submissions since no code changes.
Error
Controller
GroupFitnessSession session = unitOfWork.GroupFitnessSessionRepository.GetById(item.GroupFitnessSessionId);
session.IsConfirmed = true;
session.Attendees = item.Attendees;
unitOfWork.GroupFitnessSessionRepository.Update(session);
There are other fields to the Models that i've left out, but non of them are the same name or something to these oens
Models
public class GroupFitnessSession
{
public string GroupFitnessSessionId { get; set; }
[Required]
public virtual Trainer Trainer { get; set; }
[Required]
public virtual Location Location { get; set; }
}
public class Location
{
public string LocationId { get; set; }
public Location()
{
GroupFitnessSession = new HashSet<GroupFitnessSession>();
}
public ICollection<GroupFitnessSession> GroupFitnessSession { get; set; }
}
public class Trainer
{
public Trainer()
{
GroupFitness = new HashSet<GroupFitnessSession>();
}
public ICollection<GroupFitnessSession> GroupFitness { get; set; }
If you need any other information feel free to ask.
This is just confusing me too much, any advice would be appceiated
EDIT: showing that Location and Trainer are not empty objects
As you can see the auto generated Properties from EF aswell as the propertiy I am trying to update
This will work if you change the first line of the controller to:
GroupFitnessSession session = unitOfWork.GroupFitnessSessionRepository.GetById(item.GroupFitnessSessionId).Include(s => s.Trainer).Include(s => s.Location);
Related
I have created a class and I'm putting a list of same type as a property of that class.
Is it good or bad practice?
I am putting the same type of list because of I want to manage everything by only one object.
I don't want to create a single object and a list of object of the same type.
Any help is highly appreciated!
class AssetSection
{
public string Code { get; set; }
public string Description { get; set; }
public string SITEID { get; set; }
public string PlantID { get; set; }
public string User { get; set; }
public string UpDateTime { get; set; }
public List<AssetSection> AssetSections { get; set; }
public AssetSection(string des, string code)
{
Description = des;
Code = code;
}
}
That's ok. If you can imagine, you can design and use it.
Let's talk about entity framework. We create 2 entities like this:
public class User : IdentityUser
{
[Key]
public string Id { get; set; }
public UserProfile Profile { get; set; }
}
public class UserProfile
{
[Key]
public string UserId { get; set; }
public User User { get; set; }
}
Now, when we try to get current user:
User user = await _userManager.GetUserAsync(User);
user becomes an instance of User class now. This instance has a property name Profile, and this property has another property name User which has a type User.
It's called mapping. So, to answer your question: You can use it. But I'm not saying it's good or not based on the way to design the model.
As a general observation, such a structure is known as a rose tree, or just a tree. It enables you to write code like this:
var t = new AssetSection("foo", "bar")
{
AssetSections = new List<AssetSection>
{
new AssetSection("baz", "qux")
{
new AssetSection("corge", "garply"),
new AssetSection("fred", "plugh")
{
AssetSections = new List<AssetSection>
{
new AssetSection("xyzzy", "thud")
}
}
},
new AssetSection("quux", "quuz")
{
new AssetSection("grault", "waldo")
}
}
};
If what you want to model is a tree-like structure like that, then it's fine. On the other hand, if such a hierarchy is not what you're trying to model, then it's likely to be confusing.
By the way, the code as proposed violates the .NET framework design guidelines:
DO NOT provide settable collection properties.
DO NOT use ArrayList or List<T> in public APIs
I'm currently building an ASP.NET MVC 5 application with EF 6.1.3 linked to an SQL Server database.
My issue: I receive the following error when I attempt to save 2 or more instantiations of "PurchaseInvoiceSplitsViewModel", no issue when only 1 saved.
Unable to determine the principal end of the 'WebAS.Models.PurchaseInvoiceSplits_VehicleStock' relationship.
Multiple added entities may have the same primary key.
The issue arises at line _context.SaveChanges();
My ViewModel:
public class PurchaseInvoiceHeaderFormViewModel
{
public PurchaseInvoiceHeaderFormViewModel()
{
Splits = new List<PurchaseInvoiceSplitsViewModel>();
}
public List<PurchaseInvoiceSplitsViewModel> Splits { get; set; }
}
public class PurchaseInvoiceSplitsViewModel
{
public PurchaseInvoiceSplits PurchaseInvoiceSplits { get; set; }
public VehicleInformation VehicleInformation { get; set; }
public VehicleStock VehicleStock { get; set; }
}
My Models:
public class VehicleStock
{
[Key]
public int VehicleStockId { get; set; }
public int VehicleInformationId { get; set; }
public VehicleInformation VehicleInformation { get; set; }
}
public class PurchaseInvoiceSplits
{
[Key]
public int PurchaseInvoiceSplitsId { get; set; }
public int? VehicleStockId { get; set; }
public VehicleStock VehicleStock { get; set; }
}
public class VehicleInformation
{
[Key]
public int VehicleInformationId { get; set; }
}
Controller:
[HttpPost]
public ActionResult Save(PurchaseInvoiceHeaderFormViewModel viewModel)
{
_context.PurchaseInvoiceHeader.Add(viewModel.PurchaseInvoiceHeader);
foreach (var Split in viewModel.Splits)
{
Split.PurchaseInvoiceSplits.VehicleStockId =
Split.VehicleStock.Id;
Split.VehicleStock.VehicleInformationId =
Split.VehicleInformation.Id;
_context.VehicleInformation.Add(Split.VehicleInformation);
_context.VehicleStock.Add(Split.VehicleStock);
_context.PurchaseInvoiceSplits.Add(Split.PurchaseInvoiceSplits);
}
_context.SaveChanges();
return RedirectToAction("xxx", "xxx");
}
I have spent ages looking into this and I believe it is related to EF assigning temporary Id's of 0 to the models. This is fine when there is one model but appears to cause navigation/reference issues with multiple model instantiations. Answers to other forum posts suggest using temporary Id's which I have attempted but have not managed to get to work. Any help will be greatly appreciated. Please feel free to ask for further clarification/code snippets.
Issue resolved using Entity Framework Transactions (note, only appear to be available for version 6+). Very useful information found here:
Entity Framework Tutorials
MSDN turotials
Modifications only required within Controller:
[HttpPost]
public ActionResult Save(PurchaseInvoiceHeaderFormViewModel viewModel)
{
using (CustData Tcontext = new CustData())
{
using (DbContextTransaction transaction =
Tcontext.Database.BeginTransaction())
{
try
{
Tcontext.PurchaseInvoiceHeader.Add(viewModel.PurchaseInvoiceHeader);
Tcontext.SaveChanges();
foreach (var Split in viewModel.Splits)
{
Tcontext.VehicleInformation.Add(Split.VehicleInformation);
Split.VehicleStock.VehicleInformationId = Split.VehicleInformation.Id;
Tcontext.VehicleStock.Add(Split.VehicleStock);
Split.PurchaseInvoiceSplits.VehicleStockId = Split.VehicleStock.Id;
Split.PurchaseInvoiceSplits.PurchaseInvoiceNumberId = viewModel.PurchaseInvoiceHeader.Id;
Tcontext.PurchaseInvoiceSplits.Add(Split.PurchaseInvoiceSplits);
Tcontext.SaveChanges();
}
transaction.Commit();
}
catch (Exception ex)
{
Console.WriteLine("Error occurred." + ex);
}
}
}
return RedirectToAction("xxx", "xxx");
}
I believe that the order in which the .Add occurs is also important, hence the rearrange.
I had the same error and an unsimilar code setup, but...
I took a look at the above answer and noticed the comment at the bottom: I believe that the order in which the .Add occurs is also important, hence the rearrange.
What I did was arrange the saves in my code and was able to eliminate the error. I just thought I would post this for future error searches.
I'm using ASP.NET Core 2.0 with Angular-Frontend and Entity Framework Core 2.0. I have following DbSets: DbSet<Vocabulary> Vocabularies and DbSet<Word> Words, while the class Vocabulary contains a collection of words: List<Word> Words { get; set; }. In my API-Controller I've written a method which provides the vocabularies to the frontend as a response to an HTTP-Get-request. To test my database-connection and everything, I used the same method to create an initial record into my database:
[HttpGet]
public IEnumerable<Vocabulary> Get()
{
if (!Context.Vocabularies.Any())
{
Context.Vocabularies.Add(new Vocabulary
{
Name = "MyVocabulary",
Words = new List<Word>
{
new Word
{
PrimaryLanguage="Test",
SecondaryLanguage="Test",
Score= 0
}
}
});
Context.SaveChanges();
}
return Context.Vocabularies;
}
Now, the weird thing is that when the DB is empty, everything works as expected. When I reload the page (or restart the local IIS) and the HTTP-GET-request happens again, I get all vocabularies with correct ID's etc. but the property Words is null... I'm using a local SQL Server database. The tables seem ok, the words have the correct VocabularyId.
I just found out that there's a method called Include(). Tried it the following way: return Context.Vocabularies.Include(v => v.Words);, but didn't work either.
Vocabulary.cs:
public class Vocabulary
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Word> Words { get; set; }
}
Word.cs:
public class Word
{
public int Id { get; set; }
public string PrimaryLanguage { get; set; }
public string SecondaryLanguage { get; set; }
public double Score { get; set; }
}
Any ideas?
I believe that you have not fully defined the relationship between the two models. Based on this documentation
Relationships
You are missing the link from Word back to Vocabulary. Adding this to the Word class should solve it:
public int VocabularyId {get; set; }
I am migrating /re-developing a web app from JavaScript to the ASP.NET MVC Framework using C#/ JS (with Handlebars.NET) for my Bachelor thesis.
So far I have created a Web.API and the actual app with a form.
In the app I enter details to create a new Employee, which is then Posted to the API, which receives that Json-Object as a "Business Object" BOEmployee.
Said BOEmployee looks like this (simplified):
public class BOEmployee
{
public int ID_Employee { get; set; }
public int ID_Company { get; set; }
public string lastName { get; set; }
public string firstName { get; set; }
}
I want to map this object to two other objects, representing tables of the underlying database, to then save them to the database. The two target tables are auto generated with Entity Framework.
Here are the table objects:
1. Employee:
public partial class Employee
{
public int ID_Employee { get; set; }
public int ID_Company { get; set; }
}
2. Employee_Details:
public partial class Employee_Detail
{
public int ID_Employee_Detail { get; set; }
public int ID_Employee { get; set; }
public string lastName { get; set; }
public string firstName { get; set; }
}
Now I could map them manually by assigning every attribute but clearly that is a horribly unsustainable idea. So I was looking for a way to automate that mapping process automatically using Json.Net like this:
[HttpPost]
public BOEmployee SaveEmployee([FromBody] string employee)
{
using (var context = new myDBEntities())
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
Employee_Detail dbEmployeeDetails = serializer.Deserialize<Employee_Detail>(BOEmployee);
Employee dbEmployee = serializer.Deserialize<Employee>(BOemployee);
}
}
Now what happens when I run that code is, that the serializer-function complains that the input values cannot be null, which to my understanding is because the target Objects (e.g. Employee) do not have all attributes that are given in the serialized Json-Object.
The Error Message is this:
Value cannot be null.\r\nParameter name: input",
"ExceptionType":"System.ArgumentNullException"
Now my question would be, how can I map my object to the different Database tables? Or am I completely on the wrong path now?
Fundamental changes to the program structure cannot be made any more due to available time (and I am basically a complete beginner in programming).
I recommend AutoMapper than what you are using there.
This drives me crazy I have mode with list of two other models in it. As long as I had there iCollections it worked fine, but I had to change them to List, because I need to export the data into XML.
Model
public class PortalUser
{
//private List<UserToTeam> UserToTeam_ = new List<UserToTeam>();
//private List<Mandays> Mandays_ = new List<Mandays>();
public int ID { get; set;}
public string Name { get; set; }
[DisplayName("Last Name")]
public string LastName { get; set; }
public Role Role { get; set; }
//public virtual ICollection<Mandays> Mandays { get; set; }
public List<Mandays> Mandays { get; set; } //{ return Mandays_; }
[DisplayName("Team")]
//public virtual ICollection<UserToTeam> UserToTeam { get; set; }
public List<UserToTeam> UserToTeam { get; set; } //{ return UserToTeam_; }
public PortalUser()
{
Mandays = Mandays ?? new List<Mandays>();
UserToTeam = UserToTeam ?? new List<UserToTeam>();
}
Then I use this to get data from the DB
List<PortalUser> dbAgent = db.PortalUser.ToList();
End while debugging the result ends as Count = 0. While iCollection return the model within model correctly the List always returns Count = 0. In DB Users have Mandays and even team, but result is always empty.
I am sure I am missing something simple, please help. I can post more code if needed.
I am not sure if EF supports a List collection like that, however you need the virtual keyword in there so EF can create wrapped collections appropriately.