I have need to map PriorityId -> TcTaskPriorityId
Mapper.Configuration.RecognizePrefixes("TcTask");
Mapper.CreateMap<Task, TpTasksEntity>();
Task t = new Task{PriorityId = 1};
var te = Mapper.Map<Task, TpTasksEntity>(t);
It just does not work.
The RecognizePrefixes works for source object prefixes, i.e.:
Mapper.Configuration.RecognizePrefixes("TcTask");
Mapper.CreateMap<Task, TpTasksEntity>();
Task t = new Task { TcTaskPriorityId = 1 };
var te = Mapper.Map<Task, TpTasksEntity>(t);
For your scenario you could write a custom naming convention:
Mapper.Configuration.SourceMemberNameTransformer = s => "TcTask" + s;
Mapper.CreateMap<Task, TpTasksEntity>();
Task t = new Task { PriorityId = 1 };
var te = Mapper.Map<Task, TpTasksEntity>(t);
Use RecognizeDestinationPrefixes method.
Can you try:
Mapper.Initialize(cfg => {
cfg.RecognizePrefixes("TcTask");
cfg.CreateMap<Task, TpTasksEntity>();
});
Related
I have Linq script and I want to use projection class to get data to DTO type. I got the example for lambda expersion but getting error on the LINQ script.
Linq Script:
public class EziTransactionDto
{
... other properties
public static Expression<Func<EziTransactionEntity, EziTransactionDto>> Projection()
{
return eziTransactionDto => new EziTransactionDto
{
EziTransactionId = eziTransactionDto.Id,
LoginSiteID = eziTransactionDto.LoginSiteID,
WorkCodes = eziTransactionDto.WorkCodes
};
}
Linq query:
var ts = (from transaction in _eziTransactionRepository.GetAll<EziTransactionEntity>()
where transaction.LoginErrorCode != 0
select transaction
).Select(EziTransactionDto.Projection);
Error:
I guess the keyword Expression is odd there.
Try this:
// public static Expression<Func<EziTransactionEntity, EziTransactionDto>> Projection()
public static Func<EziTransactionEntity, EziTransactionDto> Projection()
{
return eziTransactionDto => new EziTransactionDto
{
EziTransactionId = eziTransactionDto.Id,
LoginSiteID = eziTransactionDto.LoginSiteID,
WorkCodes = eziTransactionDto.WorkCodes
};
}
After the first Select your IQueryable has already fetched the data to the local process, and made it an IEnumerable.
You could do this conversion in your Select statement:
var eziTransactionDtos = _eziTransactionRepository.EziTransactionEntities
.Where(eziTransactionEntity => eziTransationEntity.LoginErrorCode != 0)
.Select(eziTransactionEntity => new EziTransactionDto
{
EziTransactionId = eziTransactionDto.Id,
LoginSiteID = eziTransactionDto.LoginSiteID,
WorkCodes = eziTransactionDto.WorkCodes,
});
However, if you need to convert EziTransactionEntities to EziTransactionDtos on several places, it is a good idea to create a reusable extension method for IQueryable<EziTransactionEntities>.
If you are not familiar with extension methods, see extension methods demystified
public static IQueryable<EziTransactionDto> ToEziTransactionDto(
this IQueryable<EziTransactionEntity> eziTransactionEntities)
{
return eziTransactionEntities.Select(eziTransactionEntity => new EziTransactionDto
{
EziTransactionId = eziTransactionDto.Id,
LoginSiteID = eziTransactionDto.LoginSiteID,
WorkCodes = eziTransactionDto.WorkCodes,
});
Usage:
var eziTransactionDtos = eziTransactionRepository.EziTransactionEntities
.Where(eziTransactionEntity => eziTransationEntity.LoginErrorCode != 0)
.ToEziTransactionDtos();
Reusable:
var transactionWithoutWorkCodes = eziTransactionRepository.EziTransactionEntities
.Where(eziTransactionEntity => eziTransationEntity.WorkCode == null)
.ToEziTransactionDtos();
Easy to unit test:
List<EziTransactionEntity> testItems = ...
List<EziTransactionDto> expectedResults = ...
var testResults = testItems.AsQueryable().ToEziTransactionDtos();
Assert.AreQual(expectedResults, testResults, unorderedTransactionsComparer);
Easy to maintain: if you add / remove / change one property of this conversion, you'll only have to do this on one location
fond the answer
public static Expression<Func<EziTransactionEntity, EziTransactionDto>> Projection
{
get
{
return eziTransactionDto => new EziTransactionDto
{
EziTransactionId = eziTransactionDto.Id,
LoginSiteID = eziTransactionDto.LoginSiteID,
WorkCodes = eziTransactionDto.WorkCodes
};
}
}
..
var ts = (from transaction in _eziTransactionRepository.GetAll<EziTransactionEntity>()
select transaction
).Select(EziTransactionDto.Projection).ToList();
I have an attribute that I'd like to add for faceting: ApprovalFL. When I add the facet in the Algolia dashboard, it works fine until I have to reindex which ends up deleting my facets in the dashboard for some reason. I was thinking, maybe adding the attribute in my code would resolve that. I found the documentation about this step here: https://www.algolia.com/doc/api-reference/api-parameters/attributesForFaceting/
Here's the C# example they provide:
index.SetSettings(
JObject.Parse(#"{""attributesForFaceting"":[""author"",""filterOnly(category)"",""searchable(publisher)""]}")
);
If I understand correctly, this code needs to go in my backend reindexing code (found in my AdminController.cs):
public async Task<ActionResult> ReIndexData()
{
var algoliaArtistModels = Tools.BuildAlgoliaArtistModels(EntityDataAccess.GetAllAccountInfoes());
var algoliaUnaffiliatedArtistModels = Tools.BuildAlgoliaArtistModels(EntityDataAccess.GetAllUnaffiliatedAccountInfo());
var algoliaSongModels = Tools.BuildAlgoliaSongModels(EntityDataAccess.GetAllAcceptedSongs());
var artistIndexHelper = HttpContext.Application.Get("ArtistIndexHelper") as IndexHelper<ArtistAlgoliaModel>;
var unaffiliatedArtistIndexHelper = HttpContext.Application.Get("UnaffiliatedArtist") as IndexHelper<ArtistAlgoliaModel>;
var songIndexHelper = HttpContext.Application.Get("SongIndexHelper") as IndexHelper<SongAlgoliaModel>;
await artistIndexHelper.OverwriteIndexAsync(algoliaArtistModels);
await unaffiliatedArtistIndexHelper.OverwriteIndexAsync(algoliaUnaffiliatedArtistModels);
await songIndexHelper.OverwriteIndexAsync(algoliaSongModels);
return View("AlgoliaReIndexData");
}
However, I don't think I put index.setSettings in this block of code, what is the best way to set this attribute for faceting in my backend code? The ApprovalFL attribute is stored in my Song indices.
Possibly it should go somewhere here in my Tools.cs?
public static SongAlgoliaModel BuildAlgoliaSongModel(Song song)
{
var model = new SongAlgoliaModel();
var album = EntityDataAccess.GetAlbumByID(song.AlbumID);
model.AccountImageURL = album.AccountInfo.ImageURL;
model.AccountInfoID = album.AccountInfoID;
model.AccountType = album.AccountInfo.CreatorFL == true ? "Creator" : "Artist";
model.AlbumID = song.AlbumID;
model.AlbumName = album.AlbumName;
model.ApprovalFL = song.ApprovalFL;
model.Artist = album.AccountInfo.DisplayName;
model.BPM = song.BPM;
model.Duration = song.Duration;
model.FeaturedArtist = song.Artist;
model.FreeFL = album.FreeFL;
model.ImageURL = album.ImageURL;
model.iTunesURL = album.iTunesURL;
model.LabelName = album.LabelName;
model.LicenseFL = album.LicenseFL;
model.SongID = song.SongID;
model.Title = song.Title;
model.UploadDate = song.UploadDate;
model.URL = song.URL;
model.UserID = album.AccountInfo.UserID;
return model;
}
public static List<SongAlgoliaModel> BuildAlgoliaSongModels(AccountInfo accountInfo)
{
var list = new List<SongAlgoliaModel>();
var songs = EntityDataAccess.GetSongsByUserID(accountInfo.UserID).Where(x => x.ApprovalFL == true).ToList();
foreach(var item in songs)
{
var model = new SongAlgoliaModel();
model.AccountImageURL = item.Album.AccountInfo.ImageURL;
model.AccountInfoID = item.Album.AccountInfoID;
model.AccountType = item.Album.AccountInfo.CreatorFL == true ? "Creator" : "Artist";
model.AlbumID = item.AlbumID;
model.AlbumName = item.Album.AlbumName;
model.ApprovalFL = item.ApprovalFL;
model.Artist = item.Album.AccountInfo.DisplayName;
model.BPM = item.BPM;
model.Duration = item.Duration;
model.FeaturedArtist = item.Artist;
model.FreeFL = item.Album.FreeFL;
model.ImageURL = item.Album.ImageURL;
model.iTunesURL = item.Album.iTunesURL;
model.LabelName = item.Album.LabelName;
model.LicenseFL = item.Album.LicenseFL;
model.SongID = item.SongID;
model.Title = item.Title;
model.UploadDate = item.UploadDate;
model.URL = item.URL;
model.UserID = item.Album.AccountInfo.UserID;
list.Add(model);
}
return list;
}
OK for those using C# .NET it's as simple as adding it to your Global.asax.cs for example for me:
var songIndexHelper = new IndexHelper<SongAlgoliaModel>(algoliaClient, "Song", "SongID");
songIndexHelper.SetSettings(JObject.Parse(#"{""attributesForFaceting"":[""ApprovalFL""]}"));
Why do you have to re-index by the way? Best practice is to set up your index only initially.
Good day everyone,
I'm new in xunit and even in unit testing. I have a code here and I'm trying to assert two collection of list. But I have no idea how to assert and pass this test. Here's my code
[Theory]
[InlineData(1)]
public void GetAllStudents_Exempt1(int number)
{
// arrange
var studentRepo = new Mock<IStudentRepository>();
var listOfStudents = new List<Student> { new Student { StudentId = 1, Firstname = "Firstname1", Lastname = "Firstname1" },
new Student{StudentId=2, Firstname="Firstname2",Lastname="Lastname2"} };
var getAllStudentDetailsExempt1 = studentRepo.Setup(s => s.GetStudents()).Returns(listOfStudents.Where(x => x.StudentId != number));
var studentService = new StudentService(studentRepo.Object);
// act
var getStudentsDetails = studentService.ListOfStudentsExempt1(1);
// assert
// I don't have any idea how to assert
}
First a few notes:
var getAllStudentDetailsExempt1 = studentRepo
.Setup(s => s.GetStudents())
.Returns(listOfStudents.Where(x => x.StudentId != number));
you don't need var getAllStudentDetailsExempt1, you can just setup your repo-mock...
studentRepo
.Setup(s => s.GetStudents())
.Returns(listOfStudents.Where(x => x.StudentId != number));
You probably want to change:
// act
var getStudentsDetails = studentService.ListOfStudentsExempt1(1);
to use the number variable...
// act
var getStudentsDetails = studentService.ListOfStudentsExempt1(number);
So then you can assert by checking some properties:
Assert.Equals(1, getStudentsDetails.Count);
Assert.Equals("FirstName1", getStudentsDetails.First().Firstname);
etc. etc.
Give it a shot!
I implement unit tests for the engine and setup 2 different methods in the repository mock. So the first one works well, but when I do linq Select for the second one it returns 0, whereas I did setup to return specific object.
My code in Engine:
private readonly IEmployerWorkersClient _employerWorkersClient;
private readonly IJobsClient _jobsClient;
public EmployerWorkerEngine(IEmployerWorkersClient employerWorkersClient, IJobsClient jobsClient,)
{
_employerWorkersClient = employerWorkersClient;
_jobsClient = jobsClient;
}
public async Task<Grid<WorkerFiltered>> GetWorkersAsync(int employerId, GridState gridState)
{
var employerWorkers = await _employerWorkersClient.GetEmployerWorkersByEmployerIdAsync(employerId);
int? payrollId = null;
int? jobRoleId = null;
DateTime? bookedStart = null;
// !!!the following result is Empty collection!!!
List<JobRoleExtended> jobRoles = (await _jobsClient.GetJobRoleExtendedByEmployerWorkerIdsAsync(employerWorkers.Select(ew => ew.Id), payrollId, jobRoleId, bookedStart)).ToList();
// Other things
}
And hereafter my unit test class
private readonly EmployerWorkerEngine _employerWorkerEngine;
private readonly Mock<IEmployerWorkersClient> _employerWorkersClientMock;
private readonly Mock<IJobsClient> _jobClientMock;
public WorkersFilterTests()
{
_employerWorkersClientMock = new Mock<IEmployerWorkersClient>();
_jobClientMock = new Mock<IJobsClient>();
_employerWorkerEngine = new EmployerWorkerEngine(_employerWorkersClientMock.Object, _jobClientMock.Object,);
}
[Theory]
[InlineData(1)]
public async Task GetFilteredWorkersByEmployerIdSuccessSimple(int employerId)
{
// Arrange
const int employerWorkerId = 3;
var gridState = new GridState { Skip = 0, Take = 1 };
var employerWorkers = new List<EmployerWorker> { new EmployerWorker {EmployerId = 1, WorkerId = 2, Id = employerWorkerId} };
_employerWorkersClientMock.Setup(client => client.GetEmployerWorkersByEmployerIdAsync(employerId))
.ReturnsAsync(() => employerWorkers);
var jobRolesExtended = new List<JobRoleExtended>
{
new JobRoleExtended
{
EmployerWorkerId = employerWorkerId,
BookedStartDate = DateTime.UtcNow,
BookedEndDate = DateTime.UtcNow.AddDays(1),
Id = 5,
JobId = 8,
Name = "Job 5",
PayrollId = 10,
PayrollName = "Conduct"
}
};
_jobClientMock
.Setup(client => client.GetJobRoleExtendedByEmployerWorkerIdsAsync(employerWorkers.Select(ew => ew.Id), null, null, null))
.ReturnsAsync(() => jobRolesExtended);
}
So, during testing the following method returns Empty collection:
_jobsClient.GetJobRoleExtendedByEmployerWorkerIdsAsync() and I don't get why.
I assume that it related with the reference of the collection that generates linq Select, but even in this case, I don't know how to handle it for testing.
Can somebody help me with that?
does this help:
_jobClientMock.Setup(client => client.GetJobRoleExtendedByEmployerWorkerIdsAsync(It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>(), It.IsAny<int>())
.ReturnsAsync(() => jobRolesExtended);
(do check if I got the types right)
if this is the case, then your missing something with your parameters.
With Moq you have to setup the expectations correctly or else when called the mock wont match and thus not perform as expected.
In the method under test you have
int? payrollId = null;
int? jobRoleId = null;
DateTime? bookedStart = null;
List<JobRoleExtended> jobRoles =
(await _jobsClient.GetJobRoleExtendedByEmployerWorkerIdsAsync(
employerWorkers.Select(ew => ew.Id), payrollId, jobRoleId, bookedStart)
)
.ToList();
The Select statement appears to be returning a collection of Ids (IEnumerable<int>) and you have already configured the first call correctly.
You now need to correctly configure the second call to expect that collection of int Ids
_jobClientMock
.Setup(_ => _.GetJobRoleExtendedByEmployerWorkerIdsAsync(
It.IsAny<IEnumerable<int>>(),
null,
null,
null)
)
.ReturnsAsync(() => jobRolesExtended);
I have this code:
List<MyObjectOne> myListOne = new List<MyObjectOne>(){new MyObjectOne { ID = 1, field2 = 2}};
List<MyObjectTwo> myListTwo = new List<MyObjectTwo>(){new MyObjectTwo { ID = 4, field6 = "string"}};
bool hasSomething = false;
var result = new[] { new {ID = 0 }}.ToList();
if (hasSomething)
{
// Use list one.
result = myListOne.Select(x => new { ID = x.ID});
}
else
{
// Use list two.
result = myListTwo.Select(x => new { ID = x.ID });
}
foreach (var item in result)
{
// Some logic to manipulate item.ID.
item.ID;
}
What I trying to do it's to use the same anonymous type to select a list of IDs from two different lists. So I use the Select(x => new { ID = x.ID }) in order to create the anonymous type for each table in order to have only one for loop.
The error raised is "Cannot implicitly convert type IEnumerable to List"
¿any idea?
Assuming ID in MyObjectOne and MyObjectTwo are both int's, your code will work if you replace ToList with AsEnumerable:
var result = new[] { new { ID = 0 } }.AsEnumerable();
If the ID properties are some other type (e.g. long's), you need to specify that when creating the anonymous type here:
var result = new[] { new { ID = 0L } }.AsEnumerable();
Or like this:
var result = new[] { new { ID = (long)0 } }.AsEnumerable();
However, this kind of code is kind of confusing, and I wouldn't recommend it for a production environment. Here's an alternative solution that avoids creating a 'dummy' object just for implicit anonymous typing:
var result = hasSomething
? myListOne.Select(x => new { ID = x.ID })
: myListTwo.Select(x => new { ID = x.ID });