how to modify value of property has unique key in ef6 - c#

When i update value of specify product, i cannot update product.name because it has unique contain
builder.HasAlternateKey(x => x.Name);
when I call _context.SaveChange(); it cause this error message :"
The property 'Product.Name' is part of a key and so cannot be modified or marked as modified. To change the principal of an existing entity with an identifying foreign key, first delete the dependent and invoke 'SaveChanges', and then associate the dependent with the new principal"
how can I update productName field ? I leave my update code below:
try
{
var product = await _context.Products.FindAsync(request.Id);
if (product == null) throw new ProjectException($"Cannot find a product with id: {request.Id}");
product.Name = request.Name;
product.Price = request.Price;
product.Stock = request.Stock;
product.Description = request.Description;
product.productStatus = request.productStatus;
//Save image
if (request.ThumbnailImage != null)
{
var thumbnailImage = await _context.ProductImages.FirstOrDefaultAsync(i => i.IsDefault == true && i.ProductId == request.Id);
if (thumbnailImage != null)
{
thumbnailImage.FileSize = request.ThumbnailImage.Length;
thumbnailImage.ImagePath = await this.SaveFile(request.ThumbnailImage);
_context.ProductImages.Update(thumbnailImage);
}
else
{
product.ProductImages = new List<ProductImage>()
{
new ProductImage()
{
Caption = "Thumbnail image",
DateCreated = DateTime.Now,
FileSize = request.ThumbnailImage.Length,
ImagePath = await this.SaveFile(request.ThumbnailImage),
IsDefault = true,
SortOrder = 1
}
};
}
}
await _context.SaveChangesAsync();
return true;
}
catch (Exception e)
{
var xx = e.Message;//get message in debuging
var x = 1;//this line make me have time to read error message :(
return false;
}

Related

The name does not exist in the current context, ApiController, asp.net core, IEnumerable

I'm making a service that return a list IEnumerable, the trouble is that when return the element IEnumerable appear this error: The name 'ActivitiesList' does not exist in the current context
I share you my code, the error appear in the last line: return ActivitiesList;
[HttpPost]
[Route("user/get-user-activities")]
public IEnumerable<ActivitiesClass> GetUserActivities()
{
string email = User.FindFirstValue(ClaimTypes.Email);
try
{
if (!String.IsNullOrEmpty(email))
{
using (SecondAppContext db = new SecondAppContext())
{
using (var transaccion = new TransactionScope())
{
User UserModel = db.User
.Where(b => b.Email == email)
.First();
var IdUser = UserModel.Id;
IEnumerable<ActivitiesClass> ActivitiesList =
(
from activity in db.Activities
where activity.IdUser == IdUser &&
activity.DateCreated > DateTime.Now.AddDays(-3)
select new ActivitiesClass
{
dataCreated = activity.DateCreated,
description = activity.Description,
category = activity.Category,
gender = activity.Gender,
ageMin = (int)activity.AgeMin,
ageMax = (int)activity.AgeMax
}).ToList();
transaccion.Complete();
}
}
}
}
catch (Exception ex)
{
Error(ex.ToString());
}
return ActivitiesList;
}
You need to be mindful of scopes..
Yuo need to be thinking about returning an error code if something isn't as expect
You should be using the async and await pattern.
There is no need for a transaction here
Also you should use standard casing and naming conventions e.g User userModel
Untested Example
public async Task<IEnumerable<ActivitiesClass>> GetUserActivities()
{
string email = User.FindFirstValue(ClaimTypes.Email);
if (string.IsNullOrEmpty(email))
return null; // you should think about this
try
{
await using var db = new SecondAppContext();
// what are yu going to if the user is not found?
var userModel = await db.User
.Where(b => b.Email == email)
.FirstOrDefaultAsync();
if (userModel == null)
return null; // you should think about this
return await (
from activity in db.Activities
where activity.IdUser == userModel.Id && activity.DateCreated > DateTime.Now.AddDays(-3)
select new ActivitiesClass
{
dataCreated = activity.DateCreated,
description = activity.Description,
category = activity.Category,
gender = activity.Gender,
ageMin = (int) activity.AgeMin,
ageMax = (int) activity.AgeMax
}).ToListAsync();
}
catch (Exception ex)
{
Error(ex.ToString());
}
return null; // you should think about this
}
the name 'ActivitiesList' does not exist in the current context
The issue relates that you are defining the ActivitiesList in the if statement, so it will show the above error. Besides, since the IEnumerable<T> is an interface, I suggest you could define a List<ActivitiesClass> instance to store the return data.
Try to modify your code as below:
[HttpPost]
[Route("user/get-user-activities")]
public IEnumerable<ActivitiesClass> GetUserActivities()
{
string email = User.FindFirstValue(ClaimTypes.Email);
//define a List<ActivitiesClass> to store the return data.
List<ActivitiesClass> ActivitiesList = new List<ActivitiesClass>();
try
{
if (!String.IsNullOrEmpty(email))
{
using (SecondAppContext db = new SecondAppContext())
{
using (var transaccion = new TransactionScope())
{
User UserModel = db.User
.Where(b => b.Email == email)
.First();
var IdUser = UserModel.Id;
//set values for the ActivitiesList
ActivitiesList =
(
from activity in db.Activities
where activity.IdUser == IdUser &&
activity.DateCreated > DateTime.Now.AddDays(-3)
select new ActivitiesClass
{
dataCreated = activity.DateCreated,
description = activity.Description,
category = activity.Category,
gender = activity.Gender,
ageMin = (int)activity.AgeMin,
ageMax = (int)activity.AgeMax
}).ToList();
transaccion.Complete();
}
}
}
}
catch (Exception ex)
{
Error(ex.ToString());
}
return ActivitiesList; //Call the `.AsEnumerable()` method, if you want to convert the List to the IEnumerable<>.
}
After calling this method, if the IEnumerable result doesn't contain records, it means not matched data.

How to record/audit changes for Insert/Add C# EF4

Is there a non-complex way of auditing Entity Changes for insert/add?
I use the code below to record Entity changes for Edit/Update
var context = new DBEntities(connection());
try
{
BPCategory Bp = context.BPCategories.First(e => e.id == id);
Bp.Category = Category;
Bp.PercentShare = Percent;
Bp.BPCategory1 = BPCategory;
Bp.Code = Code;
Bp.Status = Inactive;
var objState = context.ObjectStateManager.GetObjectStateEntry(Bp);
var modProps = objState.GetModifiedProperties();
foreach (var propName in modProps)
{
if (!Equals(objState.OriginalValues[propName], objState.CurrentValues[propName]))
{
//save audit
}
}
context.SaveChanges();
}
catch (Exception ex)
{
throw ex;
}
But i'm struggling when it comes to add/insert. How can i do this for insert/add?
var context = new DBEntities(connection());
BPCategory Bp = new BPCategory
{
Category = Category,
PercentShare = PercentShare,
BPCategory1 = BPCategory,
Code = Code,
Status = Inactive
};
context.BPCategories.AddObject(Bp);
context.SaveChanges();

Error on SaveChanges When Using UnityContainer

I have an Asp.Net MVC 5 using Entity Framework 6. I am using Unity.MVC5 Version 1.2.3.0
The issue I am having is that I would get the following error on certain scenarios when saving to the database
Additional information: The operation failed: The relationship could
not be changed because one or more of the foreign-key properties is
non-nullable. When a change is made to a relationship, the related
foreign-key property is set to a null value. If the foreign-key does
not support null values, a new relationship must be defined, the
foreign-key property must be assigned another non-null value, or the
unrelated object must be deleted.
After troubleshooting the issue I believe it has to do with how I have Unity.MVC5 configured. Here is my Unity.Config.cs
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterTypes(AllClasses.FromLoadedAssemblies(), WithMappings.FromMatchingInterface, WithName.Default);
container.RegisterType<IUnitOfWork, UnitOfWork>(new InjectionConstructor(new MasterContext()));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
So my controller would have something like this
private IService _Service;
MyController(IService service)
{
_Service = service;
}
However it looks like the data is not refreshing, Although when I use a SQL Profiler , it shows as it is making a call but the data is not refreshed as I do a breakpoint it still has old data. If I do away with the Unity.MVC injecting the classes, then the data gets refreshed and savechanges works fine.
I am overwriting the EF Context SaveChanges , here is the code
public override int SaveChanges()
{
var autoDetectChanges = Configuration.AutoDetectChangesEnabled;
try
{
Configuration.AutoDetectChangesEnabled = false;
ChangeTracker.DetectChanges();
var errors = GetValidationErrors().ToList();
if (errors.Any())
{
throw new DbEntityValidationException("Validation errors found during save.", errors);
}
//For modified column
var changedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Modified)
.Select(t => new
{
Original = t.OriginalValues.PropertyNames.ToDictionary(pn => pn, pn => t.OriginalValues[pn]),
Current = t.CurrentValues.PropertyNames.ToDictionary(pn => pn, pn => t.CurrentValues[pn]),
objectContext = ((IObjectContextAdapter)this).ObjectContext,
ent = t,
});
foreach (var item in changedInfo)
{
if (GetTableInformation.GetTableName(item.objectContext, item.ent) != "HistoryLogs")
{
var result = GetDifference.GetChangedValues(item.Original, item.Current, item.objectContext, item.ent);
HistoryLog history = new HistoryLog();
history.Description = result[0];
history.TableFields = result[1];
history.UserId = userId;
history.TableAction = "Modified";
history.PrimaryKeyValue = Convert.ToInt32(result[2]);
history.TableName = result[3];
if (history.TableName == "MainRates")
{
MainRate rate = MainRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
history.InstitutionId = rate.InstitutionId;
}
else if (history.TableName == "ProgramRates")
{
ProgramRate rate = ProgramRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
history.InstitutionId = rate.InstitutionId;
}
else
{
int institutiondId;
if (int.TryParse(result[4], out institutiondId))
{
history.InstitutionId = institutiondId;
}
else
{
history.InstitutionId = null;
}
}
//InstitutionName and OPEID are being updated by trigger(executer after each insert operations)
//Check if there is any modified column or not
if (!string.IsNullOrEmpty(history.TableFields))
HistoryLogs.Add(history);
}
}
//For Deleted columns
var deletedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Deleted)
.Select(t => new
{
Original = t.OriginalValues.PropertyNames.ToDictionary(pn => pn, pn => t.OriginalValues[pn]),
objectContext = ((IObjectContextAdapter)this).ObjectContext,
ent = t,
});
foreach (var item in deletedInfo)
{
if (GetTableInformation.GetTableName(item.objectContext, item.ent) != "HistoryLogs")
{
var result = GetDifference.GetDeletedValues(item.Original, item.objectContext, item.ent);
HistoryLog history = new HistoryLog();
history.Description = result[0];
history.TableFields = result[1];
history.UserId = userId;
history.TableAction = "Deleted";
history.PrimaryKeyValue = Convert.ToInt32(result[2]);
history.TableName = result[3];
if (history.TableName == "MainRates")
{
int locationRateId = (int)item.Original["LocationRateId"];
history.InstitutionId = LocationRates.SingleOrDefault(l => l.Id == locationRateId).InstitutionId;
}
else if (history.TableName == "ProgramRates")
{
ProgramRate rate = ProgramRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
history.InstitutionId = rate.InstitutionId;
}
else
{
history.InstitutionId = result[4] == null ? null : (int?)int.Parse(result[4]);
}
//InstitutionName and OPEID are being updated by trigger(executer after each insert operations)
history.InstitutionName = "";
history.OpeidNumber = "";
//Check if there is any modified column or not
if (!string.IsNullOrEmpty(history.TableFields))
HistoryLogs.Add(history);
}
}
// For data that is added
string[] applicableTables = new string[] { "EligiblePrograms", "Fees", "LocationRates", "MainRates", "ProgramRates" };
var addedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Added)
.Select(t => new
{
Current = t.CurrentValues.PropertyNames.ToDictionary(pn => pn, pn => t.CurrentValues[pn]),
ObjectContext = ((IObjectContextAdapter)this).ObjectContext,
Entity = t,
}).ToList();
//Placing this here adds the primary keys to the new values before saving their history.
Configuration.ValidateOnSaveEnabled = false;
int rVal = base.SaveChanges();
foreach (var item in addedInfo)
{
string tableName = GetTableInformation.GetTableName(item.ObjectContext, item.Entity);
if (applicableTables.Contains(tableName))
{
var result = GetDifference.GetDeletedValues(item.Current, item.ObjectContext, item.Entity);
HistoryLog history = new HistoryLog();
history.Description = result[0];
history.TableFields = result[1];
history.UserId = userId;
history.TableAction = "Added";
history.PrimaryKeyValue = Convert.ToInt32(result[2]);
history.TableName = result[3];
if (history.TableName == "MainRates")
{
history.InstitutionId = ((MainRate)item.Entity.Entity).InstitutionId;
}
else if (history.TableName == "ProgramRates")
{
history.InstitutionId = ((ProgramRate)item.Entity.Entity).InstitutionId;
}
else
{
history.InstitutionId = result[4] == null ? null : (int?)int.Parse(result[4]);
}
history.InstitutionName = "";
history.OpeidNumber = "";
//Check if there is any modified column or not
if (!string.IsNullOrEmpty(history.TableFields))
HistoryLogs.Add(history);
}
}
rVal += base.SaveChanges();
return rVal;
}
finally
{
Configuration.AutoDetectChangesEnabled = autoDetectChanges;
}
}
Then my Service class will do something like this:
Header header = _uow.MyRepository.GetByHeaderId(model.Id, model.HeaderId);
header.WebAddresses = string.Join(",", model.WebAddresses.ToArray());
header.Date = DateTime.Parse(model.Date);
header.IsField1 = model.Field1;
header.Field2 = model.Field2;
header.Field3 = model.Field3;
_uow.SaveChanges();

How to update a table which has a foreign key reference using Entity Framework?

I have the following method:
public static Int32 SaveAgent(IAgent i)
{
dc = new mcollectorDataContext(ConnectionString.GetConStr());
//check if the record exists
t_agent matchID = dc.t_agents.Where(x => x.id == i.AgentID).FirstOrDefault();
try
{
if (matchID == null)
{
// if not exists add new row
t_agent _agent = new t_agent
{
wallet = i.Wallet,
branchid = GetBranchID(i.Branch),
lastupdated = i.LastUpdated,
};
dc.t_agents.InsertOnSubmit(_agent);
dc.SubmitChanges();
return _agent.id;
}
else
{
// else update row
matchID.wallet = i.Wallet;
matchID.branchid = GetBranchID(i.Branch);
matchID.lastupdated = i.LastUpdated;
dc.SubmitChanges();
return i.AgentID;
}
}
catch (Exception)
{
throw ;
}
}
This method save new reord but when i try to update, it failed, no record can be updated, but it does not throw also an error.
How can fix that problem ??
maybe try telling entity framework that the model has been modified?
try adding this before calling submitchanges
dc.Entry(matchID).State = EntityState.Modified;

Adding several related entities before calling savechanges

If your adding several related entities at once, should you call SaveChanges after each, or can it be done once? Im getting an error such as "Violation of PRIMARY KEY constraint".
Orders has a navigation property to an entity Records.
I want to add Records to an order, then call savechanges.
When I do, I get an error complaining about the primary key on Records.
I want to do something like this
Order o = new Order{.......}
Record r1 = new Record{...}
Record r2 = new Record{....}
o.Records.Add(r1)
o.Records.Add(r2)
Context.Orders.Add(o);
Context.SaveChanges()
Isnt this the right approach?
...
//populate order entity
Order o = new Order { AccountKey = iAccnt, OfficeKey = iOffice, UserKey = iUser, CreatedDate = dtCreateDate };
//save
ctx.Orders.Add(o);
//locations
Location origin = new Location
{
Order = o,
LocationTypeKey = ctx.LocationTypes.Where(a => a.TypeName == "Origin").First().LocationTypeId,
Address1 = " test address 1",
Address2 = " test Address 2",
City = oi.OriginCity,
StateKey = ctx.States.Where(a => a.StateName == oi.OriginState).First().StateId,
CountryKey = ctx.Countries.Where(a => a.CountryName == oi.OriginCountry).First().CountryId
};
Location destn = new Location
{
Order = o,
LocationTypeKey = ctx.LocationTypes.Where(a => a.TypeName == "Destination").First().LocationTypeId,
Address1 = " test address 1",
Address2 = " test Address 2",
City = oi.OriginCity,
StateKey = ctx.States.Where(a => a.StateName == oi.DestinationState).First().StateId,
CountryKey = ctx.Countries.Where(a => a.CountryName == oi.DestinationCountry).First().CountryId
};
try
{
int rows = ctx.SaveChanges();
if (rows == 0)
{
retval = false;
}
}
catch (DbEntityValidationException ex)
{
string exst = ex.ToString();
}

Categories