Foreign Class not populating after save in mvc 4 - ajax

I am saving data using Ajax and at the same time I want it to display in list. below is Class of City
public class City
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int StateId { get; set; }
[ForeignKey("StateId")]
public virtual State state { get; set; }
}
my Post method is
[HttpPost]
public ActionResult EditCity(City obj)
{
try
{
aRepository.Save(obj);
var db = aRepository.Citys.FirstOrDefault(c => c.Id == obj.Id);
return PartialView("_iCity", db);
}
catch (Exception e)
{
return Json("", JsonRequestBehavior.AllowGet);
}
}
Here db.state = null, it's not populating.

Should get you the state detail by :
or
var db = aRepository.Citys.FirstOrDefault(c => c.Id == obj.Id).Include(x=>x.StateId);

When you post the data for your server, your ViewModel should has StateId, if you are passing the Object state into it, by default Etity Framework will not persist.
I suppose you are using Lazy Loading , so you dont need to user Include to get the State entity

Related

How to update the entity in aspnetboilerplate?

I want to update an entity in database. I use the aspnetboilerplate template project. I have a method UpdateAsset in the application layer:
public async Task UpdateAsset(UpdateAssetInput input)
{
var asset = ObjectMapper.Map<Asset>(input.Asset);
asset.Domain = asset.Domain.ToLowerInvariant();
// Update Twitter Id
var twitterName = input.Asset.SocialAccounts?.TwitterInfo?.Name;
if (twitterName != null)
{
var twitterId = await _twitterActivityManager.GetTwitterIdByTwitterName(twitterName);
if (twitterId != null)
{
input.Asset.SocialAccounts.TwitterInfo.Id = twitterId;
}
}
asset.SetData<SocialAccounts>(AssetExtensionData.SocialAccounts, input.Asset.SocialAccounts);
var connectedAsset = await _assetManager.GetAsset(input.Asset.LockedPositionInfo.ConnectedAssetId);
if (connectedAsset != null)
{
input.Asset.LockedPositionInfo.ConnectedAssetUnit = connectedAsset.Unit;
}
asset.SetData<LockedPositionInfo>(AssetExtensionData.LockedPositionInfo, input.Asset.LockedPositionInfo);
asset.SetData(AssetExtensionData.WithdrawalApiInfo, input.Asset.WithdrawalApiInfo);
await _assetManager.UpdateAsset(asset);
}
UpdateAssetInput:
public class UpdateAssetInput
{
public AssetDto Asset { get; set; }
}
AssetDto:
[AutoMap(typeof(Asset))]
public class AssetDto : AuditedEntityDto<string>
{
public const int SYMBOL_LENGTH = 10;
[Required]
[MaxLength(SYMBOL_LENGTH)]
public new string Id { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
public string Website { get; set; }
[Required]
public string Domain { get; set; }
public string Logo { get; set; }
public string Organization { get; set; }
public string Unit { get; set; }
public SocialAccounts SocialAccounts { get; set; }
public LockedPositionInfo LockedPositionInfo { get; set; }
public WithdrawalApiInfo WithdrawalApiInfo { get; set; }
public decimal TotalAmount { get; set; }
public decimal Price { get; set; }
public bool IsDisable { get; set; } = false;
}
UpdateAsset in the AssetManager:
public async Task UpdateAsset(Asset asset)
{
try
{
await _assetRepository.UpdateAsync(asset);
}
catch (Exception e)
{
Logger.Error(e.Message, e);
throw new UserFriendlyException(L("AssetUpdateFailed"), asset.Name);
}
}
When I call the UpdateAsset of the application layer in front end, I get the exception:
System.InvalidOperationException: 'The instance of entity type 'Asset' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.
So how to solve the problem ?
Normally, when we update a asset entity, we will do following 3 steps:
Get asset entity from db
set updated value to asset entity
Update asset entity
based on your error message, you may get asset entity from db twice
Get asset1 entity from db - tracked
Get asset2 entity from db - tracked
set updated value to asset2 entity
Update asset2 entity
Please check if you have above code snippet

EF Core: loading related entities - circular dependency

I have 2 related entities in EF Core (database first design from an existing database) and having trouble loading one-many relationship - it's a webapi ASP.NET core 1.0 application
Brand Entity
[Table("tblBranding")]
public class Brand {
[Key]
[Column("brandingId")]
public int BrandId { get; set; }
[Column("BrandingActive")]
public bool Active { get; set; }
[JsonIgnore]
[Column("DeadBrand")]
public bool DeadBrand { get; set; }
[Column("BrandingSiteTitle")]
public string Name { get; set; }
//navigation properties
public virtual ICollection<Event> Events { get; set; }
}
Event entity:
[Table("tblEvents")]
public class Event
{
public int EventId { get; set; }
[Column("eventActive")]
public bool Active { get; set; }
[Column("eventName")]
public string Name { get; set; }
public DateTime EventCloseDate {get;set;}
public int PaxAllocationLimit { get; set; }
//navigation properties
[Column("BrandingId")]
public int BrandId { get; set; }
public virtual Brand Brand { get; set; }
public virtual ICollection<Session> Sessions { get; set; }
}
code from for FLUID API in OnModelCreating in DbContext:
modelBuilder.Entity<Event>()
.HasOne(e => e.Brand)
.WithMany(b => b.Events).HasForeignKey(e=>e.BrandId);
public virtual DbSet<Brand> Brands { get; set; }
public virtual DbSet<Event> Events { get; set; }
code from BrandsController:
[HttpGet]
public IActionResult Get() {
//var brands = from b in _context.Brands
// where b.Active == true
// orderby b.BrandName
// select b;
var brands = _context.Brands.Include(e => e.Events).Where(b => b.Active == true).OrderBy(b => b.Name);
return new ObjectResult(brands);
}
code from EventsController
// GET: api/values
[HttpGet("{id:int?}")]
public IActionResult Get(int? id) {
var events = from e in _context.Events
where e.Active == true
orderby e.Name
select e;
if (!events.Any()) {
return HttpNotFound();
}
if (id != null) {
events = events.Where(e => e.EventId == id).OrderBy(e => 0);
if (events.Count() == 0) { return HttpNotFound(); }
return new ObjectResult(events);
}
else {
return new ObjectResult(events);
}
}
When I try to load brands through the API, I get an exception:
Microsoft.Data.Entity.Storage.Internal.RelationalCommandBuilderFactory: Information: Executed DbCommand (80ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [t].[EventId], [t].[EventCloseDate], [t].[eventActive], [t].[BrandingId], [t].[EventId1], [t].[eventName], [t].[PaxAllocationLimit]
FROM [tblEvents] AS [t]
INNER JOIN (
SELECT DISTINCT [e].[BrandingSiteTitle], [e].[brandingId]
FROM [tblBranding] AS [e]
WHERE [e].[BrandingActive] = 1
) AS [e] ON [t].[BrandingId] = [e].[brandingId]
ORDER BY [e].[BrandingSiteTitle], [e].[brandingId]
Microsoft.Data.Entity.Query.Internal.SqlServerQueryCompilationContextFactory: Error: An exception occurred in the database while iterating the results of a query.
System.Data.SqlClient.SqlException (0x80131904): Invalid column name 'EventId1'.
Apart from this, is there a way to load related entities without using the "Includes" ? If I do not use include and use the standard LINQ query, the related entities are loaded as NULL
UPDATE
I'm now getting an invalid column error - i noticed in my previous code I hadn't used virtual on the ICollection in brand
now i can't figure out why is it generating EventId1 column in the SQL
EF 7 version is 1.0.0-rc1-final
UPDATE-2
After playing around with the code the Exception changed to circular dependency exception in code given the exact same code as above - I don't know why it was generating the invalid column name earlier (EventId1)
Answering my own question here - figured it out-
the 2 entities used here, I've used fully defined relationships in the EF 7
- however the JSON serializer doesn not like that,as this createsa circular dependancy - Brand Contains Events List, and each event also contains the parent brand property -
so the solution here was to add [JsonIgnore] attribute to relationship properties on the child
updated Events class:
[Table("tblEvents")]
public class Event
{
public int EventId { get; set; }
[Column("eventActive")]
public bool Active { get; set; }
[Column("eventName")]
public string Name { get; set; }
public DateTime EventCloseDate {get;set;}
public int PaxAllocationLimit { get; set; }
//navigation properties
[JsonIgnore]
[Column("brandingId")]
public virtual int BrandId { get; set; }
[JsonIgnore]
public virtual Brand Brand { get; set; }
//public virtual ICollection<Session> Sessions { get; set; }
}

How to Prevent some model attributes from Update?

I'm using Scaffolding in ASP.Net, I've a Model called "Page" which has attributes as follows
public class Page
{
private DateTime _Created_at = DateTime.Now;
private bool _IsActive = true;
public int ID { get; set; }
public string Code { get; set; }
[Required]
[DisplayName("Parent Code")]
public string ParentCode { get; set; }
[Required]
public string Title { get; set; }
************
}
Here, During Create Method, I'm updating Code attributes as follows
public ActionResult Create(Page page)
{
if (ModelState.IsValid)
{
page.Code = page.Url.Replace(" ", string.Empty);
page.IsActive = true;
db.Pages.Add(page);
db.SaveChanges();
return RedirectToAction("Details", new { id = page.ID });
}
return View(page);
}
Now, Problem is, I don't want this Code value change during Update method, I'm not included it in Edit form. But still it's updating 'NULL' value if I update.
I tried [Bind(Exclude = "Code")] for Page class, But no use.
You need a hidden field for code in your edit view. Use #Html.HiddenFor(model => model.Code).

Entity Framework: ViewModel to Domain Model

I'm building an MVC 3 website. I have a model looking like this:
public class Survey
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime DateStart { get; set; }
public DateTime DateEnd { get; set; }
// Not in view
public DateTime DateCreated { get; set; }
// Not in view
public DateTime DateModified { get; set; }
}
Based on this I also have a View Model to edit the survey information:
public class SurveyEditViewModel
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public DateTime DateStart { get; set; }
public DateTime DateEnd { get; set; }
}
When the user finishes editing I would like to persist the changes. Here's my controller post action:
[HttpPost]
public ActionResult Edit(SurveyEditViewModel model)
{
// Map the view model to a domain model using AutoMapper
Survey survey = Mapper.Map<SurveyEditViewModel, Survey>(model);
// Update the changes
_repository.Update(survey);
// Return to the overview page
return RedirectToAction("Index");
}
In my repository (it's a generic one for now) I have the following code:
public void Update(E entity)
{
using (ABCDataContext context = new ABCDataContext())
{
context.Entry(entity).State = System.Data.EntityState.Modified;
context.SaveChanges();
}
}
When this executes I get the following error: "Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries."
I guess this was to be expected. Mapping from the view model to the model doesn't give me a complete Survey object.
I could modify my controller to look like this. And then it works:
[HttpPost]
public ActionResult Edit(SurveyEditViewModel model)
{
// Map the model to a real survey
survey = _repository.Find(model.Id);
survey.Name = model.Name;
survey.Description = model.Description;
survey.DateStart = model.DateStart;
survey.DateEnd = model.DateEnd;
// Update the changes
_repository.Update(survey);
// Return to the overview page
return RedirectToAction("Index");
}
But I was wondering if a better way is available?
[HttpPost]
public ActionResult Edit(SurveyEditViewModel model)
{
// Fetch the domain model to update
var survey = _repository.Find(model.Id);
// Map only the properties that are present in the view model
// and keep the other domain properties intact
Mapper.Map<SurveyEditViewModel, Survey>(model, survey);
// Update the changes
_repository.Update(survey);
// Return to the overview page
return RedirectToAction("Index");
}

Update composite foreign key

I have a self referencing model with composite primary key in ASP.NET MVC 3 using code first approach:
public class Area
{
[Key, Column(Order=0)]
public int Id1 { get; set; }
[Key, Column(Order=1)]
public int Id2 { get; set; }
public string Name { get; set; }
public virtual Area Parent { get; set; }
}
And I would like to have a controller with create and edit operations that can work with all properties, including the composite Parent (that must be previously added to the database).
I managed to get the create method running, but for editing the complex field doesn't want to update. The input data for the following method successfully parses to the object area that also has area.Parent.Id1 and area.Parent.Id2 set.
Current code that doesn't save changes for modifications to Parent:
[HttpPost]
public ActionResult Edit(Area area)
{
try
{
if (ModelState.IsValid)
{
if (area.Parent != null)
{
area.Parent = db.Areas.Find(area.Parent.Id1, area.Parent.Id2);
if (area.Parent == null)
throw new NotFoundException();
// need to mark it as modified...
}
db.Entry(area).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
catch (NotFoundException)
{
//...
}
return View(area);
}
I found a kind of workaround if anyone needs it. Add this to the model:
[ForeignKey("Parent"), Column(Order = 0)]
public int Parent_Id1 { get; set; }
[ForeignKey("Parent"), Column(Order = 1)]
public int Parent_Id2 { get; set; }
And add this where it says "need to mark it as modified":
area.Parent_Id1 = area.Parent.Id1;
area.Parent_Id2 = area.Parent.Id2;

Resources