Entity Framework: Transform names of entities with table of aliases - entity-framework

I have entities Task and TaskAlias:
public class Task {
public int Id { get; set; }
public string Name { get; set; }
}
public class TaskAlias {
public string SourceName { get; set; }
public string TargetName { get; set; }
}
I have Web API method that returns set of Task. For result I need to replace name of Task if table TaskAlias contains alias for the name. How to solve this problem in an optimal way?

foreach (taskCollection as task) {
taskAlias = taskAliasRepository.findByTask(task);
if (taskAlias) {
task.setName(taskAlias.getTargetName);
taskRepository.save(task);
}
}

Related

LINQ query throw exception on FirstOrDefault method

I'm using EF core, and I have a many-to-many relationship between two entity
IotaProject <--> User
Here's entities & dto related to the question
public class IotaProject
{
[Key]
public int Id { get; set; }
[Required]
public string ProjectName { get; set; }
[Required]
public DateTime Create { get; set; }
public ICollection<ProjectOwnerJoint> Owners { get; set; } = new List<ProjectOwnerJoint>();
}
public class ProjectOwnerJoint
{
public int IotaProjectId { get; set; }
public IotaProject IotaProject { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
public class User
{
[Key]
public int Id { get; set; }
[Required]
public string FullName { get; set; }
[Required]
public string ShortName { get; set; }
[Required]
public string Email { get; set; }
public ICollection<ProjectOwnerJoint> OwnedProjects { get; set; } = new List<ProjectOwnerJoint>();
}
public class ApplicationDbContext : DbContext
{
public DbSet<IotaProject> IotaProjects { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<ProjectOwnerJoint> ProjectOwnerJoint { get; set; }
}
public class IotaProjectDisplayDto
{
public int Id { get; set; }
public string ProjectName { get; set; }
public DateTime Create { get; set; }
public UserMinDto Owner { get; set; }
public int Count { get; set; }
public IEnumerable<UserMinDto> Reviewers { get; set; }
}
public class UserMinDto
{
public int Id { get; set; }
public string FullName { get; set; }
public string ShortName { get; set; }
}
Following LINQ is the problem, the LINQ purpose is to convert IotaProject to IotaProjectDisplayDto, and key part is that Owners property of IotaProject is ICollection and Owner property in IotaProjectDisplayDto is just one single element UserMinDto, so I only need to get the first element of IotaProject's Owners and that's FirstOrDefault() comes.
IEnumerable<IotaProjectDisplayDto> results = _db.IotaProjects.Select(x => new IotaProjectDisplayDto
{
Id = x.Id,
ProjectName = x.ProjectName,
Create = x.Create,
Owner = x.Owners.Select(y => y.User).Select(z => new UserMinDto { Id = z.Id, FullName = z.FullName, ShortName = z.ShortName }).FirstOrDefault()
});
return results;
it throws run-time exception
Expression of type 'System.Collections.Generic.List`1[ToolHub.Shared.iota.UserMinDto]' cannot be used for parameter
of type 'System.Linq.IQueryable`1[ToolHub.Shared.iota.UserMinDto]'
of method 'ToolHub.Shared.iota.UserMinDto FirstOrDefault[UserMinDto](System.Linq.IQueryable`1[ToolHub.Shared.iota.UserMinDto])' (Parameter 'arg0')
I'm guessing it's probably related to deferred execution, but after read some posts, I still can't resolve it.
Any tips would be appreciated.
Right now, the only way I can get this work is I change type of Owner property in IotaProjectDisplayDto into IEnumrable, which will no longer need FirstOrDefault() to immediate execution. And later on, I manually get the first element in the client to display.
This issue happened in Microsoft.EntityFrameworkCore.SqlServer 3.0.0-preview7.19362.6
I end up downgrade to EF core stable 2.2.6 as Ivan suggested in comment, and everything works fine.

NullReferenceException on join with Postgres EF Provider

I have a postgres database and using asp.net core mvc (+ ef). The database is created correctly. I have two tables 'Module' and 'ModuleMenu'. I want to get all the menu's for a given module but I keep on failing to create the linq query.
Situation
Model: Module.cs
namespace project.Model
{
public class Module
{
[Required]
public string ID { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
}
}
Model: ModuleMenu.cs
namespace project.Models
{
public class ModuleMenu
{
[Required]
public string ID { get; set; }
public int ModuleID { get; set; }
[Required]
public string Title { get; set; }
[ForeignKey("ModuleID")]
public virtual Module Module { get; set; }
}
}
ApplicationDbContext.cs
namespace project.Data
{
public class ApplicationDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
public DbSet<Module> Modules { get; set; }
public DbSet<ModuleMenu> ModuleMenus { get; set; }
}
}
Query
public List<ModuleMenu> GetModuleMenus(){
var query = from m in _dbContext.ModuleMenus
join mod in _dbContext.Modules on
m.ModuleID equals mod.ID
select m;
return query.ToList();
}
Error
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[0]
An exception was thrown attempting to execute the error handler.
System.NullReferenceException: Object reference not set to an instance of an object.
Can anyone help me to correctly create the query?
Is this part correct in your code?
public int ModuleID { get; set; }
It seems that you might have had an error in the type used for the fk.
Below I changed the type to be string rather than int.
public string ModuleID { get; set; }
based on that update, the query could look like this.
public ModuleMenu[] GetModuleMenusForModule(string moduleId)
{
return _dbContext.ModuleMenus.Where(x => x.ModuleID == moduleId).ToArray();
}
I would expect that model to error (ModelID and ID are incompatible types). If that were correct, your code should work. Or simpler:
public List<ModuleMenu> GetModuleMenus()
{
return _dbContext.ModuleMenus.ToList();
}

AutoMapper is Creating Duplicate Record in DB

It could be very basic question but i have stuck with this
I have an Entity Structure like this one below
public class OrderTagGroup : Entity
{
public virtual string Name { get; set; }
public virtual List<OrderTag> OrderTags { get; set; }
}
public class OrderTag : Entity
{
public virtual string Name { get; set; }
public virtual int? OrderTagGroupId { get; set; }
}
and Its respective DTO is
public class OrderTagGroupDto : EntityDto
{
[Required]
public string Name { get; set; }
public List<OrderTagDto> OrderTags { get; set; }
}
public class OrderTagDto : EntityDto
{
[Required]
public string Name { get; set; }
public int? OrderTagGroupId { get; set; }
}
I have added the Auto mapping as well like this
Mapper.CreateMap<OrderTagGroup, OrderTagGroupDto>();
Mapper.CreateMap<OrderTagGroupDto, OrderTagGroup>();
Mapper.CreateMap<OrderTag, OrderTagDto>();
Mapper.CreateMap<OrderTagDto, OrderTag>();
Here is my Repository update
public void UpdateOrderTagGroup(OrderTagGroupDto OrderTagGroup)
{
var group = _OrderTagGroupRepo.Get(OrderTagGroup.Id);
if (group != null && group.Id > 0)
{
Mapper.Map<OrderTagGroupDto, OrderTagGroup>(OrderTagGroup,group);
}
}
My Question is, whenever my OrderTagGroupDTO goes for the update, it creates a new row in the DB and previous entry is not deleted.
Could you please help me where i am wrong ?
Automapper is for entity->DTO ..
NEVER use automapper or similar for DTO->entity it's NOT designed for that
For DTO->entity you should 'always' do it 'manually'

How to control the name of the foreign key relashionship object in EF Code First?

I have two entities in my EF Code first and they have a foreign key relationship.
public class Condition
{
public int Id { get; set; }
public string Name { get; set; }
public bool Active { get; set; }
}
public class ConditionGroup
{
public int Id { get; set; }
public Condition Condition { get; set; }
public int ConditionId { get; set; }
}
This is my entity map:
public class ConditionGroupMap : EntityTypeConfiguration<ConditionGroup>
{
public ConditionGroupMap()
{
this.ToTable("ConditionGroup");
this.HasKey(cg => cg.Id);
this.HasRequired(cg => cg.Condition).WithMany(c => c.ConditionGroups).HasForeignKey(cg => cg.ConditionId).WillCascadeOnDelete(true);
}
}
EF will create the a foreign key object in the database with the following Name:
ConditionGroup_Condition.
The problem is that this name collides with another object in the database for reasons which are beyond the scope of this question. So I would like to ask if there is a way to change this name?
Instead of doing it with the Fluent API, you could do it with Data Annotations:
public class ConditionGroup
{
public int Id { get; set; }
[ForeignKey("Condition")]
public int ConditionId { get; set; }
public Condition Condition { get; set; }
}
If that doesn't end up working you could always use the Column() Attribute to give it whatever column name you wished.

EF 4.1 code first still looking for old table that no longer exists

I am using Entity Framework 4.1 code first.
I had a table in the database with the name MaritalStatus. I deleted it and created a new table in its place called MaritalStatuses. Whenever I try to get all the records from the table I get an error:
Invalid object name 'dbo.MaritalStatus'.
The query that it is trying to execute is:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[IsActive] AS [IsActive]
FROM [dbo].[MaritalStatus] AS [Extent1]}
Why would it still be looking for table MaritalStatus that I deleted? Can it be possible that it is cached somewhere? I dropped the whole database and recreated it via scripts. Still no luck. Maybe it has an issue when it comes to the "es" part of the name?
Context class:
public class HefContext : DbContext
{
public DbSet<Bank> Banks { get; set; }
public DbSet<AccountType> AccountTypes { get; set; }
public DbSet<MaritalStatus> MaritalStatuses { get; set; }
}
View model (with partial properties):
public class EditGrantApplicationViewModel
{
public int Id { get; set; }
public string EmployeeNumber { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int MaritalStatusId { get; set; }
public IEnumerable<MaritalStatus> MaritalStatuses { get; set; }
public int BankId { get; set; }
public IEnumerable<Bank> Banks { get; set; }
public int AccountTypeId { get; set; }
public IEnumerable<AccountType> AccountTypes { get; set; }
}
Dropdown list in view for MaritalStatuses:
<td><label>Marital Status:</label> <span class="red">**</span></td>
<td>
#Html.DropDownListFor(x => x.MaritalStatusId, new SelectList(Model.MaritalStatuses, "Id", "Name", Model.MaritalStatusId), "-- Select --")
#Html.ValidationMessageFor(x => x.MaritalStatusId)
</td>
Controller:
public ActionResult Create()
{
EditGrantApplicationViewModel viewModel = new EditGrantApplicationViewModel
{
MaritalStatuses = maritalStatusService.GetAll(),
Banks = bankService.GetAll(),
AccountTypes = accountTypeService.GetAll()
};
return View(viewModel);
}
Service:
public IEnumerable<MaritalStatus> GetAll()
{
return maritalStatusRepository.GetAll();
}
Repository:
HefContext db = new HefContext();
public IEnumerable<MaritalStatus> GetAll()
{
return db.MaritalStatuses;
}
Model class:
public class MaritalStatus
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
}
You may have renamed the table in your database, but your Model class is still tied to the old name. You need to map the entity to the desired table name in the OnModelCreating method of your DbContext object
public class HefContext : DbContext
{
public DbSet<Bank> Banks { get; set; }
public DbSet<AccountType> AccountTypes { get; set; }
public DbSet<MaritalStatus> MaritalStatuses { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MaritalStatus>().ToTable("MaritalStatuses");
}
}
Update:
Apparently EF code first has some issues with the pluralization of some table names, such as Status. Out of curiosity I tested a few others and found several which also had this same issue.
I guess this is wrong:
public DbSet<MaritalStatus> MaritalStatuses { get; set; }
Should be:
public DbSet<MaritalStatuses> MaritalStatuses { get; set; }