EF update is inserting and into a different table - entity-framework

I have an MVC 5 website using EF6 code first.
The website will track golf results at events.
Here are my pocos:
public class Event
{
public int EventId { get; set; }
public string VenueName { get; set; }
public string CourseName { get; set; }
public String FirstTeeOff { get; set; }
public DateTime EventDate { get; set; }
public decimal Fee { get; set; }
public virtual ICollection<Result> Results { get; set; }
}
public class Golfer
{
public int GolferId { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public int CurrentHandicap { get; set; }
public string Email { get; set; }
public string Telephone { get; set; }
public virtual ICollection<Result> Results { get; set; }
}
public class Result
{
public int ResultId { get; set; }
public Golfer Golfer { get; set; }
public Event Event { get; set; }
public bool Attendance { get; set; }
public int HandicapPlayed { get; set; }
public int ScoreCarded { get; set; }
public int LongestDriveWins { get; set; }
public int NearestPinWins { get; set; }
public Result()
{
Event = new Event();
Golfer = new Golfer();
}
}
The POST edit action for my Result is as follows:
[HttpPost]
[Authorize]
public ActionResult Edit(ResultViewModel resultVM)
{
try
{
DomainClasses.Result resultDomain = _context.Results.Find(resultVM.GolferResults[0].ResultId);
resultDomain.Attendance = resultVM.GolferResults[0].Attendance;
resultDomain.HandicapPlayed = resultVM.GolferResults[0].HandicapPlayed;
resultDomain.ScoreCarded = resultVM.GolferResults[0].ScoreCarded;
resultDomain.LongestDriveWins = resultVM.GolferResults[0].LongestDriveWins;
resultDomain.NearestPinWins = resultVM.GolferResults[0].NearestPinWins;
_context.Results.Attach(resultDomain);
_context.SaveChanges();
return RedirectToAction("Index");
}
catch
{
return View();
}
}
I'm getting an error on the SaveChanges. I've used EF Profiler and it showed that it was trying to insert into the Event table:
INSERT [dbo].[Events]
([VenueName],
[CourseName],
[FirstTeeOff],
[EventDate],
[Fee])
VALUES (NULL,
NULL,
NULL,
'0001-01-01T00:00:00' /* #0 */,
0 /* #1 */)
SELECT [EventId]
FROM [dbo].[Events]
WHERE ##ROWCOUNT > 0
AND [EventId] = scope_identity()
Any idead why?

It's most likely because you create instances of the related entities in the Result constructor:
Event = new Event();
Golfer = new Golfer();
Remove those lines from the constructor.

Related

EF-Core query but value missing, even it show in database

here is the simple query code...
var order = await _context.ProductOrders
.FirstOrDefaultAsync(x => x.Id == orderId.ToInt());
This is the entity of ProdictOrders
public class ProductOrder
{
public int Id { get; set; }
public int MovieTicketEnrollmentId { get; set; }
public string ProductOrderStatusCode { get; set; }
public int? InvoiceId { get; set; }
public DateTime CreateDate { get; set; }
public string CreateBy { get; set; }
public DateTime? UpdateDate { get; set; }
public string UpdateBy { get; set; }
/**
* Navigation Property
*/
public MovieTicketEnrollment MovieTicketEnrollment { get; set; }
public ProductOrderStatus ProductOrderStatus { get; set; }
public ICollection<ProductOrderItem> ProductOrderItems { get; set; }
public Invoice Invoice { get; set; }
}
This data in the database
And what I got after executing query command above... what's just happening here?
MovieTicketEnrollmentId should equal to 1

EF Core Returns one Record where Many are Expected when Using Foreign Key Relationship

I have a database that stores data regarding Facilities, Doctors, and revenue for both of the previous items - FacilityRevenue and DoctorRevenue. There are also FaciltyMaster and DoctorMaster tables that have a one to many relationship with the FacilityRevenue and DoctorRevenue tables. That is, one doctor or facility master record is related to many DoctorId or FacilityId records in the FacilityRevenue and DoctorRevenue tables. I've attempted to place foreign key relationships so that DoctorId on DoctorRevenue relates to DoctorId on DoctorMaster and FacilityId on FacilityRevenue relates to FacilityId on FaclityMaster. However, I'm not confident that Entity Framework is reading this as such.
The model for each is as follows:
public partial class FacilityMaster
{
public FacilityMaster()
{
DoctorRevenue = new HashSet<DoctorRevenue>();
FacilityRevenue = new HashSet<FacilityRevenue>();
}
[Key]
public int FacilityId { get; set; }
public string FacilityName { get; set; }
public virtual ICollection<DoctorRevenue> DoctorRevenue { get; set; }
public virtual ICollection<FacilityRevenue> FacilityRevenue { get; set; }
}
public partial class DoctorMaster
{
public DoctorMaster()
{
DoctorRevenue = new HashSet<DoctorRevenue>();
}
[Key]
public int DoctorId { get; set; }
public string DoctorName { get; set; }
public string DoctorSpecialty { get; set; }
public virtual ICollection<DoctorRevenue> DoctorRevenue { get; set; }
}
public partial class DoctorRevenue
{
[Key]
public int RecordId { get; set; }
public int DoctorId { get; set; }
public int FacilityId { get; set; }
public string FacilityName { get; set; }
public string DoctorName { get; set; }
public DateTime? Date { get; set; }
public decimal? DoctorInvoices { get; set; }
public decimal? TotalRevenue { get; set; }
public virtual DoctorMaster Doctor { get; set; }
public virtual FacilityMaster Facility { get; set; }
}
public partial class FacilityRevenue
{
[Key]
public int RecordId { get; set; }
public int FacilityId { get; set; }
public string FacilityName { get; set; }
public DateTime Date { get; set; }
public decimal? TotalInvoices { get; set; }
public decimal? TotalRevenue { get; set; }
public virtual FacilityMaster Facility { get; set; }
}
I have configured, in part, my FacilityRevenueRepository as follows:
public IEnumerable<FacilityRevenue> GetFacRevenues(Int32 pageSize, Int32 pageNumber, String name)
{
var query = _context
.Set<FacilityRevenue>()
.AsQueryable()
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
if (!String.IsNullOrEmpty(name))
{
query = query.Where(item => item.FacilityName.Contains(name));
}
return query;
}
The relevant portion of my FacilityRevenueController is as follows:
[HttpGet]
[Route("GetFacilityRevenues")]
public async Task<IActionResult> GetFacilityRevenues(Int32? pageSize = 10, Int32? pageNumber = 1, String FacilityName = null)
{
var response = new ListModelResponse<FacRevViewModel>() as IListModelResponse<FacRevViewModel>;
try
{
response.PageSize = (Int32)pageSize;
response.PageNumber = (Int32)pageNumber;
response.Model = await Task.Run(() =>
{
return FacilityRevenueRepository
.GetFacRevenues(response.PageNumber, response.PageSize, FacilityName)
.Select(item => item.ToViewModel())
.ToList();
});
response.Message = String.Format("Total Records {0}", response.Model.Count());
}
catch (Exception ex)
{
response.DidError = true;
response.ErrorMessage = ex.Message;
}
return response.ToHttpResponse();
}
The DbContext is as follows:
public partial class ERPWAGDbContext : DbContext
{
public ERPWAGDbContext(DbContextOptions<ERPWAGDbContext> options)
:base(options)
{ }
public DbSet<DoctorMaster> Doctors { get; set; }
public DbSet<FacilityMaster> Facilities { get; set; }
public DbSet<DoctorRevenue> DoctorRevenue { get; set; }
public DbSet<FacilityRevenue> FacilityRevenue { get; set; }
}
When I run this using dotnet run, Postman returns just one record for GetFacilityRevenues, where several hundred are expected.
How do I ensure that all records for a given facility are returned, and likewise for doctors, when my GetFacilities and GetDoctors API methods are called?

Entity framework navigation property is null

I have two models using Entity Framework.
public class Player
{
public int PlayerId { get; set; }
public string Name { get; set; }
public string Sex { get; set; }
public string Plays { get; set; }
public string FavouriteSurface { get; set; }
}
public class SinglesMatch
{
public int SinglesMatchId { get; set; }
public int Player1Id { get; set; }
public int Player2Id { get; set; }
public int PlayerIdWinner { get; set; }
public DateTime Date { get; set; }
public string Venue { get; set; }
public string Score { get; set; }
public List<Player> Players { get; set; }
}
I am using the below code to attempt to display the Name of the player, based on the PlayerId in the SinglesMatch model matching the PlayerID from the Player model.
#foreach (var item in #Model)
{
<ul id="Players" class="bg-success"></ul>
<br/>
<h3>Date - #Html.DisplayFor(#modelItem => item.Date)</h3>
<li>Venue - #Html.DisplayFor(#modelItem => item.Venue)</li>
<li>Player 1 - #Html.DisplayFor(#modelItem => item.Players.First(p => p.PlayerId == item.Player1Id).Name)</li>
<li>Player 2 - #Html.DisplayFor(#modelItem => item.Players.First(p => p.PlayerId == item.Player2Id).Name)</li>
<li>Score- #Html.DisplayFor(#modelItem => item.Score)</li>
}
Upon debugging, the navigation property is always showing as null when the model is retrieved from my repository.
Am I using the navigation property in the correct fashion ? is there a problem with my query ?
Edit to include DbContext:
public TennisTrackerContext() : base("name=TennisTrackerContext")
{
}
public DbSet<Player> Players { get; set; }
public DbSet<PlayerRecord> PlayerRecords { get; set; }
public DbSet<SinglesMatch> SinglesMatches { get; set; }
public DbSet<DoublesMatch> DoublesMatches { get; set; }
public DbSet<Venue> Venues { get; set; }
}
}
You need to add a bridge table. Sql will create this automatically but you won't have access to the variables unless you create it in c#.
public class Player
{
public int PlayerId { get; set; }
public string Name { get; set; }
public string Sex { get; set; }
public string Plays { get; set; }
public string FavouriteSurface { get; set; }
List<PlayerInMatch> Matches { get; set; }
public Player()
{
Matches = new List<PlayerInMatch>();
}
}
public class PlayerInMatch
{
public int Id { get; set; }
public int PlayerId { get; set; }
[ForeignKey("PlayerId")]
public Player Player { get; set; }
public int SinglesMatchId { get; set; }
[ForeignKey("SinglesMatchId")]
public SinglesMatch SinglesMatch { get; set; }
}
public class SinglesMatch
{
public int SinglesMatchId { get; set; }
public int PlayerIdWinner { get; set; }
public DateTime Date { get; set; }
public string Venue { get; set; }
public string Score { get; set; }
public List<PlayerInMatch> Players { get; set; }
public SinglesMatch()
{
Players = new List<PlayerInMatch>();
}
}
static void Main(string[] args)
{
var match = new SinglesMatch();
match.Players.Select(c => c.Player.Name);
}
You need to make your navigation property virtual to enable lazy/eager loading:
public class SinglesMatch
{
public int SinglesMatchId { get; set; }
public int Player1Id { get; set; }
public int Player2Id { get; set; }
public int PlayerIdWinner { get; set; }
public DateTime Date { get; set; }
public string Venue { get; set; }
public string Score { get; set; }
public virtual List<Player> Players { get; set; }
}
Also, did you define the relationship between SinglesMatch and Singles in fluent api?
EDIT: I see you don't have any relations mapped through annotations or fluent api whatsoever, I suggest you take a look at this:
https://msdn.microsoft.com/en-us/data/jj591617.aspx

Entity Framework Linq Entity convert to CustomModel

I have the following linq to entity:
var dbShifts = DbContext.Set < SetupShift > ()
.AsNoTracking()
.Where(s => s.ShiftCode == shiftCode).ToList();
The Entity SetupShift has the following properties:
public class SetupShift
{
public int ShiftId { get; set; }
public string ShiftCode { get; set; }
public byte Day { get; set; }
public TimeSpan InTime { get; set; }
public TimeSpan OutTime { get; set; }
public int WorkHours { get; set; }
public TimeSpan LunchOut { get; set; }
public TimeSpan LunchIn { get; set; }
public bool IsActive { get; set; }
public string CategoryType { get; set; }
}
Now, I need to wrap it to a custom model ShiftModel:
public class ShiftModel
{
public int ShiftId { get; set; }
public string ShiftCode { get; set; }
public byte Day { get; set; }
public string DayName { get; set; }
public string InTime { get; set; }
public string OutTime { get; set; }
public int WorkHours { get; set; }
public string LunchOut { get; set; }
public string LunchIn { get; set; }
public bool IsActive { get; set; }
public string CategoryType { get; set; }
}
The only difference between the EF Entity model and my ShiftModel is that the TimeSpan properties are String in the Custom model.
I would like to know if there is a fast way to generate my ShiftModel from my Entity data instead of looping every entity:
List<ShiftModel> shifts = new List<ShiftModel>();
foreach(var entity in SetupShift){
....
newShiftModel = new ShiftModel();
newShiftModel.InTime = new TimeSpan(0, 0, 0).ToString(#"hh\:mm");
....
....
shifts.Add(newShiftModel);
}
You could do something like
var dbShifts = DbContext.Set < SetupShift > () .AsNoTracking() .Where(s => s.ShiftCode == shiftCode).Select(x => new ShiftModel() {
ShiftId = x.ShiftId,
ShiftCode = x.ShiftCode,
Etc.....
}).ToList();
Apologies for the poor formatting answering this from my phone.

EF code first property not mapped

The problem I'm encountering is when I try to insert a new record in a ASPxGridView which is a master of detail in an asp.net page.
This only occurs when adding a new record is required when there is no record.
EnderecoEscola entity:
namespace DAL
{
[Table("CAD_ENDERECO_ESCOLA")]
public class EnderecoEscola
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ENDESC_ID { get; set; }
[Required]
public int ESCOLA_ID { get; set; }
[Association("Escolas", "ESCOLA_ID", "ESCOLA_ID")]
[ForeignKey("ESCOLA_ID")]
public virtual Escola Escola { get; set; }
[Required]
public int TPOEND_ID { get; set; }
[ForeignKey("TPOEND_ID")]
public virtual TipoEndereco TipoEndereco { get; set; }
[Required]
public int ENDESC_UF_ID { get; set; }
[ForeignKey("ENDESC_UF_ID")]
public virtual UnidadeFederativa UnidadeFederativa { get; set; }
[Required]
public int ENDESC_MUN_iD { get; set; }
[ForeignKey("ENDESC_MUN_iD")]
public virtual Municipio Municipio { get; set; }
[StringLength(10), Required]
[MinLength(8)]
public string ENDESC_CEP { get; set; }
[StringLength(100), Required]
[MinLength(10)]
public string ENDESC_ENDERECO { get; set; }
[StringLength(15)]
public string ENDESC_NRO { get; set; }
[StringLength(25)]
public string ENDESC_COMPL { get; set; }
[StringLength(70)]
public string ENDESC_BAIRRO { get; set; }
[NotMapped]
public String TPEND_DESCRICAO { get; set; }
[NotMapped]
public String UF_SIGLA { get; set; }
[NotMapped]
public String MUN_DESCRICAO { get; set; }
}
}
DAL :
namespace DAL.utilities
{
public class OperationCadEnderecoEscola
{
public IQueryable<EnderecoEscola> GetId(int idEsc)
{
using (SecurityCtx ctx = new SecurityCtx())
{
ctx.Configuration.LazyLoadingEnabled = false;
var query = ctx.EnderecoEscola.Include("TipoEndereco").Include("UnidadeFederativa").Include("Municipio").Where(w => w.ESCOLA_ID == idEsc).OrderBy(p => p.ENDESC_ENDERECO).ToList().
Select(w => new EnderecoEscola
{
ENDESC_ID = w.ENDESC_ID,
ESCOLA_ID = w.ESCOLA_ID,
TPOEND_ID = w.TPOEND_ID,
ENDESC_UF_ID = w.ENDESC_UF_ID,
ENDESC_MUN_iD = w.ENDESC_MUN_iD,
ENDESC_CEP = w.ENDESC_CEP,
ENDESC_ENDERECO = w.ENDESC_ENDERECO,
ENDESC_NRO = w.ENDESC_NRO,
ENDESC_COMPL = w.ENDESC_COMPL,
ENDESC_BAIRRO = w.ENDESC_BAIRRO,
TPEND_DESCRICAO = w.TipoEndereco.TPEND_DESCRICAO != null ? w.TipoEndereco.TPEND_DESCRICAO : w.TPEND_DESCRICAO,
UF_SIGLA = w.UnidadeFederativa.UF_SIGLA != null ? w.UnidadeFederativa.UF_SIGLA : w.UF_SIGLA,
MUN_DESCRICAO = w.Municipio.MUN_DESCRICAO != null ? w.Municipio.MUN_DESCRICAO : w.MUN_DESCRICAO
}).Distinct().AsQueryable();
return query;
}
}
}
}
When applying for inclusion in ASPxGridView a new record and the method in DAL public IQueryable <EnderecoEscola> getId (int idEsc) is invoked to retrieve the data and they do not exists it is adding a new record on the master and detail occurs error
A field or property with name 'TPEND_DESCRICAO' was not found in the
selected data source.
Someone could guide me on how to solve the problem.
Tks.