When I want to call a property of my object property Trip from TripApplicationUser model class its values are null. So I do not know how to initialize the Trip object to get its property values later on and to now have problem with indexing in database. I have pasted here the most important parts of code.
[Authorize]
public async Task<ActionResult> Enroll(int id)
{
if (id == null)
{
return NotFound();
}
var currentTrip = await _context.Trip.FindAsync(id);
var currentUser = await _userManager.GetUserAsync(User);
var isAlreadyEnrolled = _context.TripApplicationUsers.Where(tu => tu.ApplicationUserId.Equals(currentUser.Id) && tu.TripId == id);
var UserTrips = isAlreadyEnrolled.ToList();
if (currentTrip.TripSeats > 0 && !UserTrips.Any())
{
ViewBag.process = "done";
currentTrip.TripSeats--;
_context.Update(currentTrip);
var rowToSave = new TripApplicationUser
{
TripId = currentTrip.TripId,
ApplicationUserId = currentUser.Id,
Trip = currentTrip //HOW SHOULD I INITIALIZE IT ACTUALLY?
};
_context.Add(rowToSave);
await _context.SaveChangesAsync();
} else if (UserTrips.Any())
{
ViewBag.process = "already done";
} else if(currentTrip.TripSeats <= 0)
{
ViewBag.process = "not done";
}
var UsersTrips = _context.TripApplicationUsers.Where(t => t.ApplicationUserId.Equals(currentUser.Id)).ToList();
return View(UsersTrips);
}
public class ApplicationUser : IdentityUser
{
[PersonalData]
[Column(TypeName = "nvarchar(MAX)")]
public string FirstName { get; set; }
[PersonalData]
[Column(TypeName = "nvarchar(MAX)")]
public string Surname { get; set; }
[PersonalData]
[Column(TypeName = "nvarchar(MAX)")]
public string BirthDate { get; set; }
public ICollection<TripApplicationUser> TripApplicationUsers { get; set; }
}
public class Trip
{
public int TripId { get; set; }
public string TripDate { get; set; }
public int TripDuration { get; set; }
public int TripLength { get; set; }
public int TripSeats { get; set; }
public int TrailId { get; set; }
public Trail Trail { get; set; }
public ICollection<TripApplicationUser> TripApplicationUsers { get; set; }
}
public class TripApplicationUser
{
public int TripId { get; set; }
public Trip Trip { get; set; }
public string ApplicationUserId { get; set; }
public ApplicationUser ApplicationUser { get; set; }
}
If you want your Trip object to contain data from Navigational properties you have to include them in the request.
var currentTrip = await _context.Trip.Include(trip=> trip.TripApplicationUsers).FirstOrDefaultAsync(trip => trip.TripId == id);
I have written a controller method in asp.net api that would return a viewmodel called AllocationsViewModel. The GetAllocationsViewModel contains subsets of three more viewmodels. The GetAllocationsGrouped currently returns FIRMWIDE_MANAGER_ALLOCATION and I need to return this FirmWideAllocationsViewModel instead. I have installed Automapper 8.0 and added some code to do the mapping. Is that enough to do the job. I can see only the ManagerStrategyID and ManagerStrategyID values coming through the values are comming null for the fields. I have run the original query and can see there are values for all the fields
public class FIRMWIDE_MANAGER_ALLOCATION
{
private decimal _groupPercent;
public int FIRM_ID { get; set; }
public string FIRM_NAME { get; set; }
public int? MANAGER_STRATEGY_ID { get; set; }
public int? MANAGER_FUND_ID { get; set; }
public int MANAGER_ACCOUNTING_CLASS_ID { get; set; }
public int? MANAGER_FUND_OR_CLASS_ID { get; set; }
public string MANAGER_FUND_NAME { get; set; }
public string MANAGER_ACCOUNTING_CLASS_NAME { get; set; }
public string MANAGER_STRATEGY_NAME { get; set; }
public int? PRODUCT_ID { get; set; }
public string PRODUCT_NAME { get; set; }
public int? QUANTITY { get; set; }
public decimal? NAV { get; set; }
}
public class FirmWideAllocationsViewModel
{
private decimal _groupPercent;
public int FirmID { get; set; }
public string FirmName { get; set; }
public int? ManagerStrategyID { get; set; }
public int? ManagerFundID { get; set; }
public int ManagerAccountClassID{ get; set; }
public int? ManagerFundOrClassID { get; set; }
public string ManagerFundName { get; set; }
public string ManagerAccountingClassName { get; set; }
public string ManagerStrategyName { get; set; }
public int? ProductID { get; set; }
public string ProductName { get; set; }
public int? Quantity { get; set; }
public decimal? Nav { get; set; }
}
public IHttpActionResult Details(int id, DateTime date)
{
var viewModel = GetAllocationsViewModel(id, date);
if (viewModel == null) return NotFound();
return Ok(viewModel);
}
private AllocationsViewModel GetAllocationsViewModel(int id, DateTime date)
{
var ms = GetStrategy(id);
DateTime d = new DateTime(date.Year, date.Month, 1).AddMonths(1).AddDays(-1);
if (ms.FIRM_ID != null)
{
var firm = GetService<FIRM>().Get(ms.FIRM_ID.Value);
var currentEntity = new EntityAllocationsViewModel(new EntityViewModel { EntityId = firm.ID, EntityName = firm.NAME, EntityType = EntityType.Firm });
var allocationsGrouped = Mapper.Map<List<FIRMWIDE_MANAGER_ALLOCATION>, List<FirmWideAllocationsViewModel>>(GetAllocationsGrouped(EntityType.ManagerStrategy, id, d).ToList());
var missingProducts = GetMissingProducts();
var vm = new AllocationsViewModel
{
CurrentEntity = currentEntity,
ManagerAllocations = allocationsGrouped,
MissingProducts = missingProducts
};
return vm;
}
return null;
}
public class AllocationsViewModel
{
public EntityAllocationsViewModel CurrentEntity { get; set; }
public List<FirmWideAllocationsViewModel> ManagerAllocations { get; set; }
public object MissingProducts { get; set; }
}
I have added the following code after installing autommapper 8.0
public class AutoMapperConfig
{
public static void Initialize()
{
Mapper.Initialize((config) =>
{
config.ReplaceMemberName("FIRM_ID", "FirmID");
config.ReplaceMemberName("FIRM_NAME", "FirmName");
config.ReplaceMemberName("MANAGER_STRATEGY_ID", "ManagerStrategyID");
config.ReplaceMemberName("MANAGER_FUND_ID", "ManagerFundID");
config.ReplaceMemberName("MANAGER_ACCOUNTING_CLASS_ID", "ManagerAccountClassID");
config.ReplaceMemberName("MANAGER_FUND_OR_CLASS_ID", "ManagerFundOrClassID");
config.ReplaceMemberName("MANAGER_FUND_NAME", "ManagerFundName");
config.ReplaceMemberName("MANAGER_ACCOUNTING_CLASS_NAME", "ManagerAccountingClassName");
config.ReplaceMemberName("MANAGER_STRATEGY_NAME", "ManagerStrategyName");
config.ReplaceMemberName("PRODUCT_ID", "ProductID");
config.ReplaceMemberName("PRODUCT_NAME", "ProductName");
config.ReplaceMemberName("QUANTITY", "Quantity");
config.ReplaceMemberName("NAV", "Nav");
config.CreateMap<FIRMWIDE_MANAGER_ALLOCATION, FirmWideAllocationsViewModel>().ReverseMap();
});
}
}
protected void Application_Start()
{
AutoMapperConfig.Initialize();
GlobalConfiguration.Configure(WebApiConfig.Register);
}
The issue has been resolved. I had to amend the grouping statement that is called to include all the fields . It was working fine earlier but with the upgrade of the latest entity framework, I think its the case
allocations = allocations.GroupBy(x => new { x.MANAGER_STRATEGY_ID, x.PRODUCT_ID, x.EVAL_DATE })
.Select(group => new FIRMWIDE_MANAGER_ALLOCATION { EVAL_DATE = group.First().EVAL_DATE,
FIRM_ID = group.First().FIRM_ID,
FIRM_NAME = group.First().FIRM_NAME,
MANAGER_ACCOUNTING_CLASS_ID = group.First().MANAGER_ACCOUNTING_CLASS_ID,
MANAGER_ACCOUNTING_CLASS_NAME = group.First().MANAGER_ACCOUNTING_CLASS_NAME,
MANAGER_FUND_ID = group.First().MANAGER_FUND_ID,
MANAGER_FUND_NAME = group.First().MANAGER_FUND_NAME,
MANAGER_FUND_OR_CLASS_ID = group.First().MANAGER_FUND_OR_CLASS_ID,
NAV = group.First().NAV,
Percent = group.First().Percent,
MANAGER_STRATEGY_ID = group.First().MANAGER_STRATEGY_ID,
EMV = group.Sum(x => x.EMV),
USD_EMV = group.Sum(x => x.USD_EMV),
MANAGER_STRATEGY_NAME = group.First().MANAGER_STRATEGY_NAME,
PRODUCT_ID = group.First().PRODUCT_ID,
PRODUCT_NAME = group.First().PRODUCT_NAME })
.ToList();
Pretty new to ASP.NET and programming. I have two models, two API controllers, two repositories. How do I post the data to the second model while attaching it to the first (I'm guessing by ID.) Do I possibly need a View Model? Also reading a little about unit of work. Maybe neither are necessary? Below is some code. Thanks!
Record.cs
namespace Train.Models {
public class Record {
public int Id { get; set; }
public int Quantity { get; set; }
public DateTime DateCreated { get; set; }
public bool IsActive { get; set; }
public string UserId { get; set; }
public virtual ICollection<Cars> Cars { get; set; }
}
}
Cars.cs
namespace Train.Models {
public class Cars {
public int Id { get; set; }
public string EmptyOrLoaded { get; set; }
public string CarType { get; set; }
//Hopper, flatbed, tank, gondola, etc.
public string ShippedBy { get; set; }
//UP(Union Pacific) or BNSF
public string RailcarNumber { get; set; }
//public virtual ApplicationUser ApplicationUser { get; set; }
public string UserId { get; set; }
public string RecordId { get; set; }
public virtual Record Record { get; set; }
}
}
Record Repository
public void SaveRecord(Record recordToSave) {
if (recordToSave.Id == 0) {
recordToSave.DateCreated = DateTime.Now;
_db.Record.Add(recordToSave);
_db.SaveChanges();
} else {
var original = this._db.Record.Find(recordToSave.Id);
original.Quantity = recordToSave.Quantity;
original.IsActive = true;
_db.SaveChanges();
}
}
EFRepository (Cars)
public void SaveCar(Cars carToSave) {
if (carToSave.Id == 0) {
_db.Cars.Add(carToSave);
_db.SaveChanges();
} else {
var original = this.Find(carToSave.Id);
original.EmptyOrLoaded = carToSave.EmptyOrLoaded;
original.CarType = carToSave.CarType;
original.ShippedBy = carToSave.ShippedBy;
original.RailcarNumber = carToSave.RailcarNumber;
_db.SaveChanges();
}
}
I have a table in my DB called Login. In this table I have an attribute called Head_ID, which is nullable.
Basically, you can have a chief, or you ARE the chief. In the case that you're the chief, the Head_ID should be null. In my application I have the possibility to change one's chief (Coworker changes chief, chief gets downgraded and get's a chief above him), but this int won't be set to
Service.cs
public int EditLogin(LoginDTO login)
{
try
{
var dbLogin = DAO.HourRegInstance.Login.Single(x => x.ID == login.Id);
dbLogin.Name = login.Name;
dbLogin.Username = login.Username;
if (login.Head_Id == 0)
{
//Doesn't work
dbLogin.Head_ID = null;
}
dbLogin.Role_ID = login.Role_Id;
DAO.HourRegInstance.SaveChanges();
return 1;
} catch(Exception e){
return -1;
}
}
Login.cs
public partial class Login
{
public Login()
{
this.HourRegistrationConfirmed = new HashSet<HourRegistrationConfirmed>();
this.HourRegistrationConfirmed1 = new HashSet<HourRegistrationConfirmed>();
this.Login1 = new HashSet<Login>();
this.LoginProject = new HashSet<LoginProject>();
}
public long ID { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public long Role_ID { get; set; }
public Nullable<long> Head_ID { get; set; }
public virtual ICollection<HourRegistrationConfirmed> HourRegistrationConfirmed { get; set; }
public virtual ICollection<HourRegistrationConfirmed> HourRegistrationConfirmed1 { get; set; }
public virtual ICollection<Login> Login1 { get; set; }
public virtual Login Login2 { get; set; }
public virtual Role Role { get; set; }
public virtual ICollection<LoginProject> LoginProject { get; set; }
}
How does one accomplish such task?
Solved the problem on my own.
I'm not sure what caused this problem, but after a restart of the service, everything seems to work alright now. Maybe just Entity Framework being Entity Framework?
An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception.
I'm using EF Code first and I'm getting error above when I trying do this:
public ActionResult CreateTransaction(TransactionViewModel model)
{
try
{
if (model.MemberId != 0 && model.SubcategoryId != 0 & model.CategoryId != 0)
{
Transaction t = new Transaction();
t.Amount = model.Amount;
t.Comment = model.Comment;
t.Date = DateTime.Now;
t.TransactionSubcategory = db.Subcategories.Find(model.SubcategoryId);//and i have error in this line
//i tried also this code below but it's the same error
//db.Subcategories.Find(model.SubcategoryId).Transactions.Add(t);
db.Members.Find(model.MemberId).Transactions.Add(t);
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
return RedirectToAction("CreateTransaction") ;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
return RedirectToAction("CreateTransaction");
}
}
And there is my model
public class Subcategory
{
public Subcategory()
{
IsGlobal = false;
Transactions = new List<Transaction>();
}
public int Id { get; set; }
public string Name { get; set; }
public TransactionType TypeOfTransaction { get; set; }
public Category OwnerCategory { get; set; }
public List<Transaction> Transactions { get; set; }
public bool IsGlobal { get; set; }
}
public class Transaction
{
public int Id { get; set; }
public Decimal Amount { get; set; }
public DateTime Date { get; set; }
public string Comment { get; set; }
public Subcategory TransactionSubcategory { get; set; }
public Member OwnerMember { get; set; }
}
I don't know why thats happen because in database in Transaction table i see there is column with FK.
If you need there is rest of the model
public class Budget
{
public Budget()
{
Members = new List<Member>();
}
public int Id { get; set; }
public string BudgetName { get; set; }
public string OwnerName { get; set; }
public DateTime CreatedTime { get; set; }
public List<Member> Members { get; set; }
}
public class Category
{
public Category()
{
IsGlobal = false;
}
public int Id { get; set; }
public string Name { get; set; }
public List<Subcategory> Subcategories { get; set; }
public Budget OwnerBudget { get; set; }
public bool IsGlobal { get; set; }
}
public class Member
{
public Member()
{
Transactions = new List<Transaction>();
}
public Budget OwnerBudget { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedTime { get; set; }
public List<Transaction> Transactions { get; set; }
}
public enum TransactionType
{
Income,
Expenditure
}
Try adding
public int TransactionSubcategoryId { get; set; }
public int OwnerMemberId { get; set; }
In your Transaction class.