I using ef 6.13 to get some data, and return a new class data to my app.
public List<v_apply_detail2> GetApplyList()
{
using (yoyoEntities ds = new yoyoEntities())
{
return datas = ds.v_apply_detail.Select(p => new v_apply_detail2 { apply_id = p.apply_id, time_line = ds.yoyo_apply_timeline.ToList() }).ToList();
}
}
It's runing normal.
and I want to move the Select method in a New Func, and using the dbcontext yoyoEntities(ds).
Func<v_apply_detail, v_apply_detail2> SelectOutApply(yoyoEntities ds, bool includetimeline = false)
{
return (p => new v_apply_detail2
{
apply_id = p.apply_id,
time_line = includetimeline ? ds.yoyo_apply_timeline.Where(x => x.apply_id == p.apply_id).OrderByDescending(x => x.time).ToList() : null
});
}
public List<v_apply_detail2> GetApplyList()
{
using (yoyoEntities ds = new yoyoEntities())
{
return datas = ds.v_apply_detail.Select(SelectOutApply(ds,true)).ToList();
}
}
When I call the GetApplyList function , it's get a error :Entity Framework: There is already an open DataReader associated with this Connection which must be closed first.
How do I can using the dbcontext in Func<> or Expression<> ?
think guys!
Allowing Multiple Active result sets should fix the error that you are seeing.
string connectionString = "Data Source=MSSQL1;" +
"Initial Catalog=AdventureWorks;Integrated Security=SSPI;" +
"MultipleActiveResultSets=True";
https://msdn.microsoft.com/en-us/library/h32h3abf(v=vs.110).aspx
But I believe you should be passing a queryable rather than a dbcontext.
Update:
Make the Timeline property Virtual.
public partial class v_apply_detail2 {
public long apply_id { get; set; }
public long hiring_id { get; set; }
public string hiring_title { get; set; }
public string publish_user_id { get; set; }
public string publish_company_id { get; set; }
public string user_id { get; set; }
public Nullable<System.DateTime> pre_accept_time { get; set; }
public sbyte join_type { get; set; }
public Nullable<decimal> deal_pay { get; set; }
public Nullable<System.DateTime> deal_time { get; set; }
public Nullable<System.DateTime> start_work_time { get; set; }
public Nullable<System.DateTime> finish_time { get; set; }
public string master_appraise { get; set; }
public string worker_appraise { get; set; }
public Nullable<int> master_rating { get; set; }
public Nullable<int> worker_rating { get; set; }
public int status { get; set; }
public Nullable<System.DateTime> master_rating_time { get; set; }
public Nullable<System.DateTime> worker_rating_time { get; set; }
public string hiring_snapshots { get; set; }
public virtual List<yoyo_apply_timeline> time_line { get; set; }
public member_info member_info { get; set; }
public company_info company_info { get; set; }}
Then instead of using context use the query variable:
Func<v_apply_detail, v_apply_detail2> SelectOutApply(yoyoEntities ds, bool includetimeline = false) {
return (p => new v_apply_detail2
{
apply_id = p.apply_id,
time_line = includetimeline ? p.timeline.OrderByDescending(x => x.time) : null
});}
Better way (single method):
Just to keep things simple the below should work well (just don't use datacontext to query timelines again):
public List<apply_detail_dto> GetApplyList(){
using (yoyoEntities ds = new yoyoEntities())
{
return datas = ds.v_apply_detail.Select(p => new apply_detail_dto { apply_id = p.apply_id, time_line = p.timeline }).ToList();
}}
And use a DTO object to project into (new apply_detail_dto {}).
Hope that helps.
this is may be helpful you
Expression<Func<v_apply_detail, v_apply_detail2>> SelectOutApply(yoyoEntities ds,bool includetimeline = false)
{
if (includetimeline)
return (p) => new v_apply_detail2
{
apply_id = p.apply_id,
time_line = ds.yoyo_apply_timeline.Where(x => x.apply_id == p.apply_id).OrderByDescending(x => x.time).ToList()
};
return (p) => new v_apply_detail2
{
apply_id = p.apply_id
};
}
public List<v_apply_detail2> GetApplyList()
{
using (yoyoEntities ds = new yoyoEntities())
{
return datas = ds.v_apply_detail.Select(ds,SelectOutApply(true)).ToList();
}
}
Thank Amanvir Singh Mundra.
here is my poco classes
public partial class v_apply_detail2
{
public long apply_id { get; set; }
public long hiring_id { get; set; }
public string hiring_title { get; set; }
public string publish_user_id { get; set; }
public string publish_company_id { get; set; }
public string user_id { get; set; }
public Nullable<System.DateTime> pre_accept_time { get; set; }
public sbyte join_type { get; set; }
public Nullable<decimal> deal_pay { get; set; }
public Nullable<System.DateTime> deal_time { get; set; }
public Nullable<System.DateTime> start_work_time { get; set; }
public Nullable<System.DateTime> finish_time { get; set; }
public string master_appraise { get; set; }
public string worker_appraise { get; set; }
public Nullable<int> master_rating { get; set; }
public Nullable<int> worker_rating { get; set; }
public int status { get; set; }
public Nullable<System.DateTime> master_rating_time { get; set; }
public Nullable<System.DateTime> worker_rating_time { get; set; }
public string hiring_snapshots { get; set; }
public List<yoyo_apply_timeline> time_line { get; set; }
public member_info member_info { get; set; }
public company_info company_info { get; set; }
}
i has same class in my project to provide data service
so, my Problem is the query performance and Code reuse.
if i add the dbcontext in my select func ,like this
using (yoyoEntities dd = new yoyoEntities())
{
v_apply_detail2 result = new v_apply_detail2();
{
result.apply_id = x.apply_id;
result.time_line = dd.yoyo_apply_timeline.Where(p => p.apply_id == x.apply_id).OrderByDescending(p => p.time).ToList();
}
return result;
}
i can get the result , but the trigger many sql query .
but use
return datas = ds.v_apply_detail.Select(p => new v_apply_detail2 { apply_id = p.apply_id, time_line = ds.yoyo_apply_timeline.ToList() }).ToList();
the sql query only one。so ,i want to reuse the ds。i think the expression can do this,and i can't find the road.
Related
I have to pass some data from a source DB to another target DB both handled using Entity Framework just with two different DbContexts.
This is my code:
internal async static Task UploadNewsList(DateTime dataStart, TextWriter logger)
{
try
{
NumberFormatInfo provider = new NumberFormatInfo();
provider.NumberDecimalSeparator = ".";
using (BDContentsDataModel buffettiContext = new BDContentsDataModel())
{
List<News> newsList = buffettiContext.News.Where(x => x.Online && x.DataPub >= dataStart.Date).ToList();
using (DirectioDBContext directioContext = new DirectioDBContext())
{
foreach(News buffettiNews in newsList)
{
bool hasAuth = false;
List<DirectioAutore> listAutori = null;
List<DirectioAutore> listAutoriFinal = new List<DirectioAutore>();
if (buffettiNews.AutoreList?.Count > 0)
{
hasAuth = true;
listAutori = EntitiesHelper.GetAutoriDirectio(buffettiNews.AutoreList.ToList(), directioContext);
foreach (var autore in listAutori)
{
int dirAuthId = 0;
bool exist = false;
foreach (var dirAut in directioContext.Autori)
{
if (dirAut.Nome.IndexOf(autore.Nome, StringComparison.InvariantCultureIgnoreCase) >= 0 &&
dirAut.Cognome.IndexOf(autore.Cognome, StringComparison.InvariantCultureIgnoreCase) >= 0)
{
exist = true;
dirAuthId = dirAut.Id;
}
}
//directioContext.Autori.
//Where(x => autore.Cognome.ToLowerInvariant().Contains(x.Cognome.ToLowerInvariant()) &&
// autore.Nome.ToLowerInvariant().Contains(x.Nome.ToLowerInvariant())).Any();
if (!exist)
{
directioContext.Autori.Add(autore);
directioContext.SaveChanges();
}
else
{
autore.Id = dirAuthId;
}
listAutoriFinal.Add(autore);
}
}
DirectioNews directioNews = EntitiesHelper.CreateDirectioNewsModel(buffettiNews);
if (hasAuth)
directioNews.AutoreList = listAutoriFinal;
if (directioNews == null)
throw new Exception("[News] - Trasformazione entità fallita");
directioContext.News.Add(directioNews);
await directioContext.SaveChangesAsync();
}
}
}
}
catch (Exception ex)
{
logger.WriteLine(ex.Message);
throw ex;
}
}
This is the target DbContext:
public class DirectioDBContext : DbContext
{
public DirectioDBContext() : base("name=DirectioCMSDataModel") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// ...
modelBuilder.Entity<DirectioNews>()
.HasMany(s => s.AutoreList)
.WithMany(x => x.News)
.Map(cs =>
{
cs.MapLeftKey("Autore_Id");
cs.MapRightKey("News_Id");
cs.ToTable("NewsAutore");
});
}
public virtual DbSet<DirectioNews> News { get; set; }
public virtual DbSet<DirectioVideo> Video { get; set; }
public virtual DbSet<DirectioMedia> Media { get; set; }
public virtual DbSet<DirectioAutore> Autori { get; set; }
public virtual DbSet<DirectioVideoAutori> VideoAutori { get; set; }
}
This is the interested target Parent Model:
[Table("News")]
public partial class DirectioNews
{
[Key]
public int Id { get; set; }
public string Titolo { get; set; }
public int IdDocType { get; set; }
public string Abstract { get; set; }
public string Testo { get; set; }
[Required]
public DateTime DataPub { get; set; }
public int IdUmbraco { get; set; }
public int CreatedById { get; set; }
public DateTime CreateDate { get; set; }
public int? UpdateById { get; set; }
public DateTime? UpdateDate { get; set; }
public int? DeletedById { get; set; }
public DateTime? DeletedDate { get; set; }
public int? ResumedById { get; set; }
public DateTime? ResumedDate { get; set; }
public int? PublishedById { get; set; }
public DateTime? PublishedDate { get; set; }
public int? UnpublishedById { get; set; }
public DateTime? UnpublishedDate { get; set; }
public DateTime? PublishedFrom { get; set; }
public DateTime? PublishedTo { get; set; }
public bool Online { get; set; }
public bool APagamento { get; set; }
public int IdConsulenzaOld { get; set; }
public bool IsDeleted { get; set; }
public virtual ICollection<DirectioAutore> AutoreList { get; set; }
public bool IsFromOtherCMS { get; set; } = false;
public string Name { get; set; }
public int? NodeId { get; set; }
public int SortOrder { get; set; } = 0;
public Guid PlatformGuid { get; set; }
public Guid SourceGuid { get; set; }
// Permette l'accesso anche senza login
public bool FreeWithoutLogin { get; set; }
// nasconde dalla visualizzazione della lista normale del frontend, visibile solo attraverso l'etichetta campagna
public bool HideFromList { get; set; }
#region parametri per riferimenti temporali
public int? Day { get; set; } = null;
public int? Month { get; set; } = null;
public int? Year { get; set; } = null;
#endregion
public int? MediaId
{
get; set;
}
}
And this is the target Child model
[Table("Autori")]
public class DirectioAutore
{
[Key]
public int Id { get; set; }
public string Nome { get; set; }
[Required]
public string Cognome { get; set; }
public string DescrizioneBreve { get; set; }
public string Descrizione { get; set; }
public string Email { get; set; }
public string Immagine { get; set; }
public string Tipo { get; set; } // Maschio Femmina Team
public string Twitter { get; set; }
public int IdUmbraco { get; set; }
public bool Online { get; set; }
public DateTime? PublishedFrom { get; set; }
public DateTime? PublishedTo { get; set; }
public int IdOld { get; set; }
public bool IsDeleted { get; set; }
public int? NodeId { get; set; }
public string Name { get; set; }
public int CreatedById { get; set; } = 1;
public DateTime CreateDate { get; set; }
public int? UpdateById { get; set; }
public DateTime? UpdateDate { get; set; }
public int? DeletedById { get; set; }
public DateTime? DeletedDate { get; set; }
public int? ResumedById { get; set; }
public DateTime? ResumedDate { get; set; }
public int? PublishedById { get; set; }
public DateTime? PublishedDate { get; set; }
public int? UnpublishedById { get; set; }
public DateTime? UnpublishedDate { get; set; }
public string MetaaDescrBreve { get; set; }
public int? MediaId
{
get; set;
}
public Guid PlatformGuid { get; set; }
public Guid SourceGuid { get; set; }
public string MetaTitle { get; set; }
public string MetaDescription { get; set; }
public virtual ICollection<DirectioNews> News { get; set; }
}
EntityFramework generated this table to handle this many-to-many relation:
When it saves the entity, it goes into the catch statement and show this error:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.NewsAutore_dbo.Autori_Autore_Id". The conflict occurred in database "DirectioContentsCMS_Stage_20201102", table "dbo.Autori", column 'Id'
What could be the problem?
Thank you so much
[SOLVED]
I was wrongly pointing LeftKey and RightKey into the DbContext, they was not pointing to the correct FKs.
I just inverted FKs:
modelBuilder.Entity<DirectioNews>()
.HasMany(s => s.AutoreList)
.WithMany(x => x.News)
.Map(cs =>
{
cs.MapLeftKey("Autore_Id");
cs.MapRightKey("News_Id");
cs.ToTable("NewsAutore");
});
instead of
modelBuilder.Entity<DirectioNews>()
.HasMany(s => s.AutoreList)
.WithMany(x => x.News)
.Map(cs =>
{
cs.MapLeftKey("News_Id");
cs.MapRightKey("Autore_Id");
cs.ToTable("NewsAutore");
});
Because MapLeftKey points to the parent entity of the navigation property specified in the HasMany method and MapRightKey points to the parent entity of the navigation property specified in the WithMany. I was doing exactly the opposite.
Then i moved the association after actually saving the news to prevent multiple authors creation:
// ...
DirectioNews directioNews = EntitiesHelper.CreateDirectioNewsModel(buffettiNews);
if (directioNews == null)
throw new Exception("[News] - Trasformazione entità fallita");
directioContext.News.Add(directioNews);
directioContext.SaveChanges();
if (hasAuth)
{
List<int> ids = listAutori.Select(s => s.Id).ToList();
List<DirectioAutore> r = directioContext.Autori.Where(x => ids.Contains(x.Id)).ToList();
directioNews.AutoreList = r;
directioContext.SaveChanges();
}
I have the following Linq statement that is currently not working.
var result = ClientDATARepository.AllIncluding(c => c.Jobs, c => c.ClientNotes, c => c.Suburb).Where(x => x.Id == id).Select(fetchedClient =>
new ClientDetailsDto {
Id = fetchedClient.Id,
ClientNo = fetchedClient.ClientNo,
Company = fetchedClient.Company,
IsWarrantyCompany = fetchedClient.IsWarrantyCompany,
CompanyName = fetchedClient.CompanyName,
ClientFirstName = fetchedClient.ClientFirstName,
ClientLastName = fetchedClient.ClientLastName,
MobilePhone = fetchedClient.MobilePhone,
DeActivated = fetchedClient.DateDeActivated.HasValue ? "true" : "false",
CreatedOn = EF.Property<DateTime>(fetchedClient, "CreatedOn").ToString("dd/MM/yyyy", CultureInfo.CurrentCulture),
ModifiedOn = EF.Property<DateTime>(fetchedClient, "ModifiedOn").ToString("dd/MM/yyyy", CultureInfo.CurrentCulture),
ClientNotes = fetchedClient.ClientNotes.Select(fetchedClientNote =>
new ClientNoteDto {
id = fetchedClientNote.Id,
Details = fetchedClientNote.Details,
}) as IQueryable<ClientNoteDto>
The initial method ClientDATARepository.AllIncluding is from the repository and is suppose to return the full details of a client:
public virtual IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties)
{
IQueryable<T> query = _context.Set<T>();
return includeProperties.Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
}
Which should include all associated entities requested... which works to obtain a client however no ClientNotes are returned yet there are clientNotes in the database for the selected client.
The Dto I am trying to fill in is a follows:
public class ClientDetailsDto
{
public ClientDetailsDto()
{
}
[Key]
public int Id { get; set; }
public string ClientNo { get; set; }
public bool Company { get; set; }
public bool IsWarrantyCompany { set; get; }
public string CompanyName { get; set; }
public string ClientFirstName { get; set; }
public string ClientLastName { get; set; }
public string MobilePhone { get; set; }
public string DeActivated { get; set; }
public string CreatedOn { get; set; }
public string CreatedBy { get; set; }
public string ModifiedOn { get; set; }
public string ModifiedBy { get; set; }
public int SuburbId { get; set; }
public AddressDto Address { get; set; }
public IQueryable<ClientJobDto> ClientJobs { get; set; }
public IQueryable<ClientNoteDto> ClientNotes { get; set; }
}
ClientNoteDto is also presented for completeness:
public class ClientNoteDto
{
[Key]
public int id { get; set; }
public string Details { get; set; }
public string NoteType { get; set; }
public string CreatedOnDate { get; set; }
public string CreatedOnTime { get; set; }
public string CreatedBy { get; set; }
public string ModifiedOnDate { get; set; }
public string ModifiedOnTime { get; set; }
public string ModifiedBy { get; set; }
}
How do I get the IQueryable statement to return all the notes for this client as part of the result?
It's been a while since I have done this, but I know there is an easy way to do this that I have forgotten. Below I have a class designed to populate a single record of a data object. But I cannot get the values from another table (related by foreign key) to populate using the lambda statement because I am missing something (the two values being pulled in from another table below can be seen as dto.LeaseName and dto.CarName). How should I write the lambda for the object dm?
public StationUnloadingLogDTO GetSingleRecordforLog(int Id)
{
StationUnloadingLogDTO dto = new StationUnloadingLogDTO();
StationUnloadingLog dm = new StationUnloadingLog();
dm = entity.StationUnloadingLog
.Where(x => x.Id == Id)
.FirstOrDefault();
dto.Id = dm.Id;
dto.DateLogged = dm.DateLogged;
dto.DriverName = dm.DriverName;
dto.TruckNumber = dm.TruckNumber;
dto.CarName = dm.Carrier.CarName;
dto.CarrierId = dm.CarrierId;
dto.SpecificGravity = dm.SpecificGravity;
dto.LactMeterOpen = dm.LactMeterOpen;
dto.LactMeterClose = dm.LactMeterClose;
dto.EstimatedBarrels = dm.EstimatedBarrels;
dto.TicketNumber = dm.TicketNumber;
dto.LeaseNumber = dm.LeaseNumber;
dto.LeaseName = dm.Company.CmpName;
dto.StationId = dm.StationId;
return dto;
}
Here are the related data classes
namespace Data.Models
{
public partial class Company
{
public Company()
{
StationUnloadingLog = new HashSet<StationUnloadingLog>();
}
public string CmpId { get; set; }
public string CmpName { get; set; }
public string CmpAddress1 { get; set; }
public string CmpAddress2 { get; set; }
public int? CmpCity { get; set; }
public string CmpZip { get; set; }
public string CmpPrimaryphone { get; set; }
public ICollection<StationUnloadingLog> StationUnloadingLog { get; set; }
}
public class StationUnloadingLogDTO
{
public int Id { get; set; }
public DateTime? DateLogged { get; set; }
public string DriverName { get; set; }
public string TruckNumber { get; set; }
public string CarrierId { get; set; }
public string CarName { get; set; }
public decimal? SpecificGravity { get; set; }
public decimal? LactMeterOpen { get; set; }
public decimal? LactMeterClose { get; set; }
public int? EstimatedBarrels { get; set; }
public string TicketNumber { get; set; }
public string LeaseName { get; set; }
public string LeaseNumber { get; set; }
public string StationId { get; set; }
}
public partial class StationUnloadingLog
{
public int Id { get; set; }
public DateTime? DateLogged { get; set; }
public string DriverName { get; set; }
public string TruckNumber { get; set; }
public string CarrierId { get; set; }
public decimal? SpecificGravity { get; set; }
public decimal? LactMeterOpen { get; set; }
public decimal? LactMeterClose { get; set; }
public int? EstimatedBarrels { get; set; }
public string TicketNumber { get; set; }
public string LeaseNumber { get; set; }
public string StationId { get; set; }
public Carrier Carrier { get; set; }
public Company Company { get; set; }
public Tractorprofile Tractorprofile { get; set; }
}
public partial class Carrier
{
public Carrier()
{
StationUnloadingLog = new HashSet<StationUnloadingLog>();
}
public string CarId { get; set; }
public string CarName { get; set; }
public string CarAddress1 { get; set; }
public string CarAddress2 { get; set; }
public int? CtyCode { get; set; }
public string CarZip { get; set; }
public string CarContact { get; set; }
public ICollection<StationUnloadingLog> StationUnloadingLog { get; set; }
}
You should query for your record with child entities like this.
dm = DbSet<StationUnloadingLog>
.Where(x => x.Id == Id).Include(x => x.Carrrier)
.FirstOrDefault();
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();
I'm trying to use this reply https://stackoverflow.com/a/5942176/5741268 For bulk inserts. But this procedure is entering duplicate.
My Entities
public class Empresa
{
public int EmpresaId { get; set; }
public string CNPJ { get; set; }
public string CPF { get; set; }
public string IE { get; set; }
public string xNome { get; set; }
public string cMun { get; set; }
public string CNAE { get; set; }
//Endereço
public string COD_PAIS { get; set; }
public string UF { get; set; }
public string CEP { get; set; }
public string END { get; set; }
public string NUM { get; set; }
public string COMPL { get; set; }
public string BAIRRO { get; set; }
public string FONE { get; set; }
}
public class NFe
{
public int NFeId { get; set; }
//public int NFePartId { get; set; }
public string versao { get; set; }
public string chave { get; set; }
public string ide_mod { get; set; }
public string ide_serie { get; set; }
public string ide_nNF { get; set; }
public DateTime? ide_dEmi { get; set; }
public DateTime? ide_dSaiEnt { get; set; }
public string ide_tpNF { get; set; }
public decimal? TOTAIS_vBC { get; set; }
public decimal? TOTAIS_vICMS { get; set; }
public decimal? TOTAIS_vBCST { get; set; }
public decimal? TOTAIS_vST { get; set; }
public decimal? TOTAIS_vProd { get; set; }
public decimal? TOTAIS_vFrete { get; set; }
public decimal? TOTAIS_vSeg { get; set; }
public decimal? TOTAIS_vDesc { get; set; }
public decimal? TOTAIS_vII { get; set; }
public decimal? TOTAIS_vIPI { get; set; }
public decimal? TOTAIS_vPIS { get; set; }
public decimal? TOTAIS_vCOFINS { get; set; }
public decimal? TOTAIS_vOutro { get; set; }
public decimal? TOTAIS_vNF { get; set; }
public string infCpl { get; set; }
public bool cancelada { get; set; } = false;
public virtual NFePart NFePart { get; set; }
public virtual Empresa Empresa { get; set; }
public virtual ICollection<NFeItem> NFeItemLista { get; set; }
}
public class NFePart
{
public int NFePartId { get; set; }
public string NOME { get; set; }
public string COD_PAIS { get; set; }
public string CNPJ { get; set; }
public string IE { get; set; }
public string UF { get; set; }
public string CEP { get; set; }
public string END { get; set; }
public string NUM { get; set; }
public string COMPL { get; set; }
public string BAIRRO { get; set; }
public string COD_MUN { get; set; }
public string FONE { get; set; }
public virtual Empresa Empresa { get; set; }
public virtual ICollection<NFe> NFe { get; set; }
//Uso interno, não mapeado no banco de dados
[NotMapped]
public int COD_PART { get; set; }
}
Here is my code:
List<NFe> notas = new List<NFe>();
//populate notas
DataContext context = null;
try
{
List<Empresa> nEmpresas = notas.DistinctBy(x => new { x.Empresa.CNPJ }).Select(x => x.Empresa).ToList();
foreach (Empresa empresaToAdd in nEmpresas)
{
context = new DataContext();
context.Configuration.AutoDetectChangesEnabled = false;
int count = 0;
List<NFe> notasFilter;
notasFilter = notas.Where(x => x.Empresa.CNPJ == empresaToAdd.CNPJ).ToList();
int commitCount = 2000;
foreach (var notaInsert in notasFilter)
{
++count;
context = AddToContext(context, notaInsert, count, commitCount, true, notasFilter.Count);
}
}
}
finally
{
if (context != null)
context.Dispose();
}
My AddtoContext function
private static DataContext AddToContext(DataContext context, NFe entity, int count, int commitCount, bool recreateContext, int totalNfe)
{
//if has already inserted -> Attach entity.Empresa
if ((count > commitCount && commitCount != 0) || entity.Empresa.EmpresaId != 0)
{
context.Empresa.Attach(entity.Empresa);
}
if (context.NFePart.Any(p => p.CNPJ == entity.NFePart.CNPJ && p.Empresa.CNPJ == entity.Empresa.CNPJ))
{
context.NFePart.Attach(entity.NFePart);
}
context.Set<NFe>().Add(entity);
if (commitCount == 0 || count % commitCount == 0 || count == totalNfe)
{
context.SaveChanges();
if (recreateContext)
{
context.Dispose();
context = new DataContext();
context.Configuration.AutoDetectChangesEnabled = false;
}
}
return context;
}
After save changes, the EF insert duplicate
In the code I'm going through all have in "notas" and only filtering the "empresaToAdd" in question. but when the loop moves on to the next "empresaToAdd" it inserts again notes the previous company in the loop even using Dispose, and recreating the context
NFeItemMap
public class NFeItemMap : EntityTypeConfiguration<NFeItem>
{
public NFeItemMap()
{
ToTable("NFeItem");
HasKey(x => x.NFeItemId);
Property(x => x.infAdProd).HasColumnType("text").IsMaxLength();
//one-to-many
HasRequired(s => s.NFe)
.WithMany(s => s.NFeItemLista);
HasRequired(x => x.Empresa)
.WithMany();
}
}