I'm a beginner. I try to get all the positions of the employee, but only the position of the first employee is returned. Employees and positions relationship is many-to-many. Whatever you do, the result is the same :(
View Model
public class DivisionEmployeeViewModel
{
public DivisionEmployee DivisionEmployees { get; set; }
public Division Division { get; set; }
public IEnumerable<DivisionEmployee> DivisionEmployeeList { get; set; }
public IEnumerable<EmployeePosition> EmployeePositionList { get; set; } // get 1 obj
public IEnumerable<SelectListItem> DivisionEmployeeListDropDown { get; set; }
}
Action Details
[HttpGet]
public async Task<IActionResult> Details(int id)
{
var model = new DivisionEmployeeViewModel
{
DivisionEmployeeList = await _db.DivisionEmployeesModel.Include(x => x.Employee)
.Include(x => x.Division).Where(x => x.Division_Id == id).ToListAsync(),
// Get only 1 obj
EmployeePositionList = await _db.EmployeePositions.Include(x => x.Position)
.Include(x => x.Employee).Where(x => x.Employee_Id == id).ToListAsync(),
//
DivisionEmployees = new DivisionEmployee()
{
Division_Id = id
},
Division = await _db.Divisions.FirstOrDefaultAsync(x => x.Id == id)
};
List<int> tempAssignedList = model.DivisionEmployeeList.Select(x => x.Employee_Id).ToList();
List<int> tempAssignedList2 = model.EmployeePositionList.Select(x => x.Position_Id).ToList(); // ? Get only 1 obj
// Get all items who's Id isn't in tempAuthorsAssignedList and tempCitiesAssignedList
var tempList = await _db.Employees.Where(x => !tempAssignedList.Contains(x.Id)).Where(x => !tempAssignedList2.Contains(x.Id)).ToListAsync();
model.DivisionEmployeeListDropDown = tempList.Select(x => new SelectListItem
{
Text = x.FullName,
Value = x.Id.ToString()
});
return View(model);
}
Project GitHub https://github.com/ValencyJacob/DepartmentManagementApp-Many-to-Many
Your Division_Id and Employee_Id are both id in Details(int id)?And tempAssignedList2 is a list of positionId,why you use .Where(x => !tempAssignedList2.Contains(x.Id)) to compare employeeId with positionId? – Yiyi You
Related
First of all look at my code: this is ConceptDto:
public Guid ConceptId { get; set; }
public string ConceptName { get; set; }
public string ConceptLatinName { get; set; }
public List<ConceptSubDto> ConceptSubSidiary { get; set;}
This is the ConceptSubDto:
public Guid ConceptSubId { get; set; }
public string ConceptSubName { get; set; }
and I have domains like that.
Now this is my application layer that have logic I want to get these by id and return just one ConceptDto but I don't have any idea have to map these dtos with domain models:
public async Task<ConceptManagementDto> GetConceptById(Guid id)
{
var concept = await _conceptManagementRepository.Query()
.Include(x => x.conceptSubSidiaries)
.GetOneAsync(x => x.Id == id);
return new ConceptManagementDto
{
ConceptManagementId = concept.Id,
ConceptName = concept.ConceptName,
ConceptLatinName = concept.ConceptLatinName,
ConceptSubSidiary = ??
};
}
This query should effective if your DTO has less fields:
public async Task<ConceptManagementDto> GetConceptById(Guid id)
{
return await _conceptManagementRepository.Query()
.Where(x => x.Id == id)
.Select(x = new ConceptManagementDto
{
ConceptManagementId = x.Id,
ConceptName = x.ConceptName,
ConceptLatinName = x.ConceptLatinName,
ConceptSubSidiary = x.ConceptSubSidiaries
.Select(sub => new ConceptSubDto
{
ConceptSubId = sub.ConceptSubId,
ConceptSubName = sub.ConceptSubName
})
.ToList()
}).First();
}
Initially I was using automapper for this but its seems way harder for me to implement it.
Basically, I just want to return an empty list instead of null values. I can do this on projects level but not on teammates level. The API must not return a null because the UI that consumes it will have an error.
Sample of my implementation below:
Projects = !Util.IsNullOrEmpty(x.Projects) ? x.Projects : new List<ProjectsDto>(),
Ill highly appreciate if someone can guide me on how to manually map this with null/empty checking.
If you can also provide and example using automapper that too will be very helpful.
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public List<ProjectsDto> Projects { get; set; }
}
public class ProjectsDto
{
public string Status { get; set; }
public List<TeammatesDto> Teammates { get; set; }
}
public class TeammatesDto
{
public string TeammateName { get; set; }
public string PreviousProject { get; set; }
}
//Get by Id
var employee = await _context.Employees
.Where(x => x.id.Equals(request.Id)
.FirstOrDefaultAsync(cancellationToken);
//Map employee
EmployeeDto ret = new EmployeeDto()
{
Id = employee.id,
Name = employee.Name,
Projects = null //TODO: map manually
}
//Get all employees
var employees = await _context.Employees.AsNoTracking()
.ToListAsync(cancellationToken);
//Map here
IList<EmployeeDto> list = new List<EmployeeDto>();
foreach (var x in employees)
{
EmployeeDto dto = new EmployeeDto()
{
Id = x.id,
Name = x.Name,
Projects = null //TODO: map manually
};
list.Add(dto);
}
return list;
Instead of materializing full entities, do the following:
var query = _context.Employees
.Select(e = new EmployeeDto
{
Id = e.id,
Name = e.Name,
Projects = e.Projects.Select(p => new ProjectDto
{
Status = p.Status,
Templates = p.Templates.Select(t => new TemplateDto
{
TeammateName = t.TeammateName,
PreviousProject = t.PreviousProject
}).ToList()
}).ToList()
}
);
var result = await query.ToListAsync();
how to retrieve partial object?
{
Id:123,
Name:"david",
Languages:[{b:"en"},{b:"ru"}]
}
public async Task<myObj> Get(long id, string lang=null)
{
FilterDefinition<myObj> filter = Builders<myObj>.Filter.Eq(s => s.Id, id)
& Builders<myObj>.Filter.ElemMatch(l => l.Languages, s => s.b== lang);
ProjectionDefinition<myObj> projection = Builders<Symptom>.Projection
.Include(d => d.Id)
.Include(d => d.Name)
.Include(d => d.Languages[-1]);
FindOptions<myObj> options = new FindOptions<myObj> { Projection = projection };
using (IAsyncCursor<myObj> cursor = await db.Collection.FindAsync(filter, options))
{
return cursor.SingleOrDefault();
}
}
if i call function get(123,"cn") i expect to get:
{
Id:123,
Name:"david",
Languages:null
}
instead of null.
how to fix the query to achieve my demand?
i think this will get the job done:
public async Task<myObj> Get(long id, string lang = null)
{
var res = await db.Collection.AsQueryable()
.Where(m =>
m.Id == id &&
m.Languages.Any(l => l.b == lang))
.SingleOrDefaultAsync();
return res ?? new myObj { _Id = id, Languages = null };
}
If you want to display the languages only when they match (and null if none match up), then try the following
public async Task<myObj> Get(long id, string lang = null)
{
FilterDefinition<myObj> filter = Builders<myObj>.Filter.Eq(s => s.Id, id)
var result = await collection.Find(filter).SingleOrDefaultAsync();
if (result != null)
result.Languages = result.Languages?.Where(lng => lng.b.Equals(lang)).ToList();
return result;
}
You will get your object that you want based on the ID.. then further it will return only those languages that match up with language that you are passing (null or otherwise).
It's working. I don't know what you mean by "instead of null".
One minor thing, that you would like to not include Languges, instead you projected the Languages to an array range with the [-1]. So it's just return last element of the array. The final code is:
> db.ItemWithLanguages.find()
{ "_id" : ObjectId("5dfb57c9692d22eefa6e0cfe"), "Id" : 123, "Name" : "david", "Languages" : [ { "B" : "en" }, { "B" : "cn" } ] }
internal class MyObj
{
public long Id { get; set; }
[BsonId]
[BsonElement("_id")]
public ObjectId MyId { get; set; }
public string Name { get; set; }
public List<Language> Languages { get; set; }
}
internal class Language
{
public string B { get; set; }
}
public static async Task<MyObj> Get(IMongoCollection<MyObj> collection, long id, string lang = null)
{
FilterDefinition<MyObj> filter = Builders<MyObj>.Filter.Eq(s => s.Id, id)
& Builders<MyObj>.Filter.ElemMatch(l => l.Languages, s => s.B == lang);
// excluding d.Languages by not including it.
// it makes Languages = null.
ProjectionDefinition<MyObj> projection = Builders<MyObj>.Projection
.Include(d => d.Id)
.Include(d => d.Name);
FindOptions<MyObj> options = new FindOptions<MyObj> { Projection = projection };
using (IAsyncCursor<MyObj> cursor = await collection.FindAsync(filter, options))
{
return cursor.SingleOrDefault();
}
}
...
string connectionString = "mongodb://localhost:27017";
var client = new MongoClient(connectionString);
var db = client.GetDatabase("test");
var myObjs = db.GetCollection<MyObj>("ItemWithLanguages");
MyObj ret;
Task.Run(async () => { ret = await Get(myObjs, 123, "cn"); }).ConfigureAwait(false).GetAwaiter()
.GetResult();
I'm trying to query on a property of type IEnumerable int to find all documents in the collection that contain an integer value in this property.
I've tried to accomplish this with an index on the property to return a list of id's which satisfy the query. I am projecting the id's in the query however I'm getting a list of id 0's.
Index
public class Merchants_CategoryId : AbstractIndexCreationTask<Merchant>
{
public class Result
{
public int MerchantId { get; set; }
public IEnumerable<int> CategoryIds { get; set; }
}
public Merchants_CategoryId()
{
Map = merchants => merchants.Select(merchant => new
{
CategoryIds = merchant.Header.CategoryIds,
MerchantId = merchant.Header.Id
});
}
}
Query
return await session
.Query<Merchants_CategoryId.Result, Merchants_CategoryId>()
.Where(x => x.CategoryIds.Any(c => c == categoryId))
.Select(x => x.MerchantId)
.ToListAsync();
Index:
public class Merchants_CategoryId : AbstractIndexCreationTask<Merchant>
{
public class Result
{
public int MerchantId { get; set; }
public int CategoryId { get; set; }
}
Map = merchants => from merchant in merchants
from categoryId in merchant.Header.CategoryIds
select new
{
MerchantId = merchant.Header.Id,
CategoryId = categoryId
};
Index(x => x.CategoryId, FieldIndexing.Yes);
Store(x => x.MerchantId, FieldStorage.Yes);
}
Query:
return await session
.Query<Merchants_CategoryId.Result, Merchants_CategoryId>()
.Where(x => x.CategoryId == categoryId)
.Select(x => x.MerchantId)
.ToListAsync();
I have two tables in Database:
PostCalculationLine
PostCaluclationLineProduct
PostCalculationLineProduct(table2) contains Foriegn key of PostCalucationLineId(table1)
In C# code I have two different Models for these two tables as follows:
public class PostCalculationLine : BaseModel
{
public long Id{ get; set; }
public string Position { get; set; }
public virtual Order Order { get; set; }
public virtual Task Task { get; set; }
//some other properties go here
public virtual IList<PostCalculationLineProduct> PostCalculationLineProducts { get; set; }
}
and
public class PostCalculationLineProduct : BaseModel
{
public long Id {get;set;}
public string Description { get; set; }
//some other properties go here
}
Now in Entityframework code, I fetch data from PostCalculationLineProduct as follows:
PostCalculationLineRepository pclr = new PostCalculationLineRepository();
DataSourceResult dsrResult = pclr.Get()
.SelectMany(p => p.PostCalculationLineProducts)
.Where(c => c.Product.ProductType.Id == 1 && c.DeletedOn == null)
.Select(c => new HourGridViewModel()
{
Id = c.Id,
Date = c.From,
EmployeeName = c.Employee != null ?c.Employee.Name:string.Empty,
Description= c.Description,
ProductName = c.Product != null?c.Product.Name :string.Empty,
From = c.From,
To = c.Till,
Quantity = c.Amount,
LinkedTo = "OrderName",
Customer ="Customer"
PostCalculationLineId = ____________
})
.ToDataSourceResult(request);
In the above query I want to get PostCalculationLineId(from Table1) marked with underLine. How can I achieve this?
Thanks
You can use this overload of SelectMany to achieve this:-
DataSourceResult dsrResult = pclr.Get()
.SelectMany(p => p.PostCalculationLineProducts,
(PostCalculationLineProductObj,PostCalculationLineObj) =>
new { PostCalculationLineProductObj,PostCalculationLineObj })
.Where(c => c.PostCalculationLineProductObj.Product.ProductType.Id == 1
&& c.PostCalculationLineProductObj.DeletedOn == null)
.Select(c => new HourGridViewModel()
{
Id = c.PostCalculationLineProductObj.Id,
Date = c.PostCalculationLineProductObj.From,
//Other Columns here
PostCalculationLineId = c.PostCalculationLineObj.Id
};
This will flatten the PostCalculationLineProducts list and returns the flattened list combined with each PostCalculationLine element.