It Friday. My brain is fried. This is very simple and I'm ashamed for asking this:
I simply want to query against my Event table (which has a non-null Start Time and nullable End time).However, given my unit test, I keep getting 2 records back (the 2:00 and the 4:00 records, not just the 2:00 as I'd expect)
SELECT
EventId,
TaskId,
MachineId,
LoginId,
EventStartTimeUtc,
EventEndTimeUtc,
OpCode,
UnitId,
PositionId,
WebId,
Comment,
MakereadyCount,
GrossCount,
NetCount,
PerpetualGross,
PerpetualNet,
PerpetualMakeready,
TaskState,
EventTypeId,
IsAutoEvent,
IsTransferred,
LastUpdatedTimeUtc
FROM Event
WHERE MachineId = #MachineId#
AND EventStartTimeUtc >= #StartTimeUtc#
AND (EventEndTimeUtc IS NULL
OR ((EventEndTimeUtc IS NOT NULL) AND EventEndTimeUtc <![CDATA[<=]]> #EndTimeUtc#))
[Test]
public void ShouldSelectEventsInRange()
{
//Arrange
TaskDto testTask = _testRepository.CreateTask(new TaskDto { TaskId = 1234567 }, true);
var machineId = ((ArtemisRepository)_testRepository).CreateMachine(123, "MR40SIM", "0V7", 200, 100, 555555); //Requires a 555555 down-task to exist in database
EventRecordDto result = _testRepository.CreateEvent(new EventRecordDto {TaskId = testTask.TaskId, MachineId = machineId, EventStartTimeUtc = new DateTime(2014, 4, 15, 1, 50, 0), OpCode = "100", MakereadyCount = 1752, GrossCount = 5660, NetCount = 2512, Comment = "Test Event", IsAutoEvent = false, IsTransferred = false});
EventRecordDto result2 = _testRepository.CreateEvent(new EventRecordDto {TaskId = testTask.TaskId, MachineId = machineId, EventStartTimeUtc = new DateTime(2014, 4, 15, 2, 0, 0), OpCode = "100", MakereadyCount = 1752, GrossCount = 5660, NetCount = 2512, Comment = "Test Event", IsAutoEvent = false, IsTransferred = false});
EventRecordDto result3 = _testRepository.CreateEvent(new EventRecordDto {TaskId = testTask.TaskId, MachineId = machineId, EventStartTimeUtc = new DateTime(2014, 4, 15, 4, 0, 0), OpCode = "100", MakereadyCount = 1752, GrossCount = 5660, NetCount = 2512, Comment = "Test Event", IsAutoEvent = false, IsTransferred = false});
//Act
var results = _testRepository.SelectEventsInRange(machineId, new DateTime(2014, 4, 15, 2, 0, 0), new DateTime(2014, 4, 15, 3, 59, 59));
//Assert
Assert.IsTrue(results.Count == 1, "{0} records came, instead of the 1 record expeted!", new object[] { results.Count });
Assert.IsTrue(results.Any(r => r.EventId == result2.EventId), "Expected Event (Id: {0}), Actual Event (ID: {1})", new object[] { result2.EventId, results[0].EventId});
}
The query asks for records where the EventStartTimeUtc is greater than or equal to 2:00, which both those records are, and where the EventEndTimeUtc is null, which they both are.
Did you mean EventStartTimeUtc where you have EventEndTimeUtc in the WHERE clause?
Related
Good morning. I am writing a unit test to validate that my API handler is sorting the collection properly. As you can see, it's mocked data and I intentionally created the test data out of order to test the OrderBy functionality. Once the handler returns the DTO collection, I want to validate that the "act" collection is in the same order as my "expectedDTO" collection. Here's the code:
[TestMethod]
public async Task GetByDay_ReturnsDtoList_WhenFound()
{
var testData = TestMethodData();
var expectedCalendarDto = ExpectedDto();
var testCalendar = testData;
var query = new GetCalendarByDaysQuery();
_mockCalendarRepo.Setup(m => m.GetItemsAsync(It.IsAny<ISpecification<CalendarDay>>(), null, null))
.ReturnsAsync(testCalendar);
var sut = new GetCalendarByDaysHandler(_mockCalendarRepo.Object, _mapper);
var act = await sut.HandleAsync(query);
Assert.IsNotNull(act);
Assert.IsInstanceOfType(act, typeof(IEnumerable<CalendarDto>));
Assert.AreEqual(expectedCalendarDto, act);
}
private GetItemsResult<IEnumerable<CalendarDay>> TestMethodData()
{
var testData = new GetItemsResult<IEnumerable<CalendarDay>>();
testData.ContinuationToken = null;
testData.Results = new List<CalendarDay>()
{
new CalendarDay { Id = "4-5-4|2021-04-01", FiscalYear = 2021, CalendarType = "4-5-4", Quarter = 2, Period = 4, CalendarDate = "2021-04-01", WeekOfYear = 13, DayOfYear = 61, WeekOfPeriod = 1 },
new CalendarDay { Id = "4-5-4|2021-08-01", FiscalYear = 2021, CalendarType = "4-5-4", Quarter = 3, Period = 8, CalendarDate = "2021-08-01", WeekOfYear = 24, DayOfYear = 121, WeekOfPeriod = 1 },
new CalendarDay { Id = "4-5-4|2021-01-01", FiscalYear = 2021, CalendarType = "4-5-4", Quarter = 1, Period = 1, CalendarDate = "2021-01-01", WeekOfYear = 1, DayOfYear = 1, WeekOfPeriod = 1 }
};
return testData;
}
private IEnumerable<CalendarDto> ExpectedDto()
{
var testDto = new List<CalendarDto>()
{
new CalendarDto { FiscalYear = 2021, CalendarType = "4-5-4", Quarter = 1, Period = 1, CalendarDate = "2021-01-01", WeekOfYear = 1, DayOfYear = 1, WeekOfPeriod = 1 },
new CalendarDto { FiscalYear = 2021, CalendarType = "4-5-4", Quarter = 2, Period = 4, CalendarDate = "2021-04-01", WeekOfYear = 13, DayOfYear = 61, WeekOfPeriod = 1 },
new CalendarDto { FiscalYear = 2021, CalendarType = "4-5-4", Quarter = 3, Period = 8, CalendarDate = "2021-08-01", WeekOfYear = 24, DayOfYear = 121, WeekOfPeriod = 1 }
};
return testDto;
}
Currently, in trying to compare the two collections, the test is failing saying that they aren't equal.
Assert.AreEqual failed. Expected:<System.Collections.Generic.List`1[cscentcalendar.infrastructure.DTOs.CalendarDto]>. Actual:<System.Collections.Generic.List`1[cscentcalendar.infrastructure.DTOs.CalendarDto]>.
Not sure what I'm doing wrong. Any assistance would be greatly appreciated.
I believe I solved the problem by using fluent assertion and adding the following line of code to test the two collections. Let me know if this is incorrect. Thanks again!
expectedCalendarDto.Should().BeEquivalentTo(act);
How to translate the following SQL query into C# Linq:
SELECT * FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY StuffConditionId, StuffId ORDER BY StuffDayOfYear) AS RowNumber
FROM Stuff) rop
WHERE rop.RowNumber = 1;
Here is a partial dataset:
StuffId,StuffValue,StuffConditionId,StuffDayOfYear
2,9340,NULL,1
2,9340,NULL,2
2,9340,NULL,3
11,78,NULL,267
11,78,NULL,268
11,78,NULL,269
43,0,3,130
43,0,3,131
43,0,3,132
43,0,2,133
45,0,2,134
45,0,2,135
45,0,2,148
55,0,2,309
55,0,2,332
55,0,3,333
Answer Summary: The answer is to first build a in-memory list of stuffs, i.e. local list variable, then apply the LINQ query as shown in answer below.
Without some actual data I couldn't test this. But here's how this can be done, assuming stuff is your collection (aka table):
var firstInCollection = Stuff
.OrderBy(x => x.StuffDayOfYear)
.ToList() // Load in memory, then do groupby and select first due to EF Core
.GroupBy(x => new { condition = x.StuffConditionId, stuff = x.StuffId })
.Select(g => g.First());
Ok, I've tried this on a data table with a list of countries. Here are my results:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY SUBSTRING(CountryCode, 1, 1) ORDER BY CountryCode) AS RowNumber
FROM Lookup.Country) rop
WHERE rop.RowNumber = 1;
and got the following results in SQL
Then I used the following Linq statement. This is using Linq2SQL in LinqPad connected to my Microsoft SQL Database:
Countries
.OrderBy(c => c.CountryName)
.GroupBy(c => c.CountryName[0])
.Select(g => g.First())
And got the following result:
Which correlates with the SQL results.
Here's the example with your example data
void Main()
{
var stuffs = new []
{
new Stuff { StuffId = 2, StuffValue = 9340, StuffConditionId = null, StuffDayOfYear = 1 },
new Stuff { StuffId = 2, StuffValue = 9340, StuffConditionId = null, StuffDayOfYear = 2 },
new Stuff { StuffId = 2, StuffValue = 9340, StuffConditionId = null, StuffDayOfYear = 3 },
new Stuff { StuffId = 11, StuffValue = 78, StuffConditionId = null, StuffDayOfYear = 267 },
new Stuff { StuffId = 11, StuffValue = 78, StuffConditionId = null, StuffDayOfYear = 268 },
new Stuff { StuffId = 11, StuffValue = 78, StuffConditionId = null, StuffDayOfYear = 269 },
new Stuff { StuffId = 43, StuffValue = 0, StuffConditionId = 3, StuffDayOfYear = 130 },
new Stuff { StuffId = 43, StuffValue = 0, StuffConditionId = 3, StuffDayOfYear = 131 },
new Stuff { StuffId = 43, StuffValue = 0, StuffConditionId = 3, StuffDayOfYear = 132 },
new Stuff { StuffId = 43, StuffValue = 0, StuffConditionId = 2, StuffDayOfYear = 133 },
new Stuff { StuffId = 45, StuffValue = 0, StuffConditionId = 2, StuffDayOfYear = 134 },
new Stuff { StuffId = 45, StuffValue = 0, StuffConditionId = 2, StuffDayOfYear = 135 },
new Stuff { StuffId = 45, StuffValue = 0, StuffConditionId = 2, StuffDayOfYear = 148 },
new Stuff { StuffId = 55, StuffValue = 0, StuffConditionId = 2, StuffDayOfYear = 309 },
new Stuff { StuffId = 55, StuffValue = 0, StuffConditionId = 2, StuffDayOfYear = 332 },
new Stuff { StuffId = 55, StuffValue = 0, StuffConditionId = 3, StuffDayOfYear = 333 }
};
var firstInCollection = stuffs
.OrderBy(x => x.StuffDayOfYear)
.GroupBy(x => new { condition = x.StuffConditionId, stuff = x.StuffId })
.Select(g => g.First())
.Dump();
}
class Stuff
{
public int StuffId { get; set; }
public int StuffValue { get; set; }
public int? StuffConditionId { get; set; }
public int StuffDayOfYear { get; set; }
}
This results in the following:
I have the following problem :
I created a class Actual. This is the mapping to the table:
ToTable("actuals");
HasKey(x => x.Id);
Property(x => x.Id).HasColumnName("actuals_sk");
...;
Property(x => x.PersonId).HasColumnName("actuals_by_sk");
Property(x => x.AssignmentId).HasColumnName("evaluation_task_id");
Property(x => x.JobCodeId).HasColumnName("job_cd_sk");
Property(x => x.ProjectId).HasColumnName("is_sk");
Now when I do a DbSet.Add(entity) where the entity is the actual instance, I keep getting the same error :
Cannot insert the value NULL into column 'person_sk', table 'aariworx_app.dbo.person'; column does not allow nulls. INSERT fails.
Now the strange thing is, that I provide all the necessary entities when mapping the properties.
Person person = new Person()
{ Id = 77,
Name = actualVM.Person.Name,
CreationDate = new DateTime(2014, 02, 04, 19, 53, 08, 000),
User = actualVM.Person.UserName,
Active = 1,
ContractHrs = 38,
ContractDays = Convert.ToDecimal("5,00"),
HoursFullDay = Convert.ToDecimal("7,60"),
HoursHalfDay = Convert.ToDecimal("3,80"),
MaxMoreHours = 80,
WarnMoreHours = 70,
Freelancer = 0,
AuthMethod = Model.Utils.AuthMethod.AD,
EmailSend = 0,
HourlyCost = 45 };
Assignment assignment = new Assignment() { Id = 3, Description = "Projectleiding", DTS = new DateTime(2006, 1, 5, 18, 30, 6, 000) };
JobCode jobCode = new JobCode() { Id = actualVM.JobCode.JobCodeId, Description = actualVM.JobCode.Description, CostCenter = 10, CostType = "F", LongDescription = "Ontwikkeling van de aariXa-website", Closed = 0, Date = new DateTime(2007, 5, 16, 2, 23, 12, 000) };
Project project = new Project() { Id = actualVM.Project.ProjectId, Description = actualVM.Project.Project, Date = new DateTime(2007, 5, 16, 2, 23, 12, 000) };
return new Actual()
{
Id = actualVM.Id,
...,
Assignment = assignment ,
AssignmentId = assignment.Id,
JobCode = jobCode,
JobCodeId = jobCode.Id,
Project = project,
ProjectId = project.Id,
Person = person,
PersonId = person.Id
};
So I don't know what is going wrong.
When I look at the queries that are being performed, there is an INSERT for person happening, which I don't need, since the person already exists.
Can anyone help me?
I noticed that when I do the savechanges to save my "actual" to the database, that the following query is also executed and I don't understand why :
INSERT [dbo].[person]([name], [user], [person_DTS], [pwd], [active_yn], [contract_hrs], [contract_days], [hours_full_day], [hours_half_day], [max_more_hours], [warn_more_hours], [freelancer_yn], [auth_method], [email_sent], [artikel_aarifact], [Uurkost])
VALUES (#0, #1, #2, NULL, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12, NULL, #13)
SELECT [person_sk]
FROM [dbo].[person]
WHERE ##ROWCOUNT > 0 AND [person_sk] = scope_identity()
And since I'm passing the Id of the person, I don't see why the query should by using scope_identity()
I have LINQ sql (see below, thanks to Cameron ). I am trying to get a property (ItemCode) from class First without using that in Group by clause.
How do I do that?
Don't use First.ItemCode in group by but still want it in output by First.Begin, First.End order by decending.
public class First
{
public string Account;
public DateTime Begin;
public DateTime End;
public decimal Amount;
public string ItemCode;
}
public class Second
{
public string Account;
public DateTime Begin;
public DateTime End;
public decimal Amount;
}
List<First> firstAccount = new List<First>();
List<Second> secondAccount = new List<Second>();
firstAccount.Add(new First()
{
Account = "1234",
Begin = new DateTime(2014, 5, 13),
End = new DateTime(2014, 6, 12),
Amount = 9999,
ItemCode = "AAA"
});
firstAccount.Add(new First()
{
Account = "1234",
Begin = new DateTime(2014, 6, 13),
End = new DateTime(2014, 7, 7),
Amount = 1000,
ItemCode = "AAA"
});
firstAccount.Add(new First()
{
Account = "1234",
Begin = new DateTime(2014, 6, 13),
End = new DateTime(2014, 7, 14),
Amount = 0,
ItemCode = ""
});
firstAccount.Add(new First()
{
Account = "1234",
Begin = new DateTime(2014, 7, 7),
End = new DateTime(2014, 7, 14),
Amount = 1000,
ItemCode = "BBB"
});
secondAccount.Add(new Second()
{
Account = "1234",
Begin = new DateTime(2014, 5, 13),
End = new DateTime(2014, 6, 12),
Amount = 9999
});
secondAccount.Add(new Second()
{
Account = "1234",
Begin = new DateTime(2014, 6, 13),
End = new DateTime(2014, 7, 14),
Amount = 2000
});
var result = from account in (from first in firstAccount
join second in secondAccount
on first.Account equals second.Account
where
((first.Begin >= second.Begin && first.Begin <= second.Begin) &&
(first.End >= second.Begin && first.End <= second.End))
select new
{
first.Account,
second.Begin,
second.End,
first.Amount,
first.ItemCode
})
group account by new {account.Account, account.Begin, account.End }
into groupedAccounts
select new
{
groupedAccounts.Key.Account,
groupedAccounts.Key.Begin,
groupedAccounts.Key.End,
Sum = groupedAccounts.Sum(a => a.Amount)
};
One way to get the itemcode is to change the last select.
Add this line
Itemcode = String.Join(" ",groupedAccounts.Select(q=> q.ItemCode))
after Sum = groupedAccounts.Sum(a => a.Amount),
It should produce itemcode
foreach (var data in result)
{
Console.WriteLine(data.Account + " " + data.Itemcode);
}
Output
1234 AAA
1234 AAA
Have a list like this:
01/01/2009, 120
04/01/2009, 121
30/12/2009, 520
01/01/2010, 100
04/01/2010, 101
31/12/2010, 540
I need to find the last value for each year, e.g. the result would be 520, 540?
var lastValues = records.OrderByDescending(r => r.Date)
.GroupBy(r => r.Date.Year)
.Select(g => g.First().Value);
class Program
{
static void Main()
{
var list = new[]
{
new { Date = new DateTime(2009, 1, 1), Value = 120 },
new { Date = new DateTime(2009, 4, 1), Value = 121 },
new { Date = new DateTime(2009, 12, 30), Value = 520 },
new { Date = new DateTime(2010, 1, 1), Value = 100 },
new { Date = new DateTime(2009, 4, 1), Value = 101 },
new { Date = new DateTime(2010, 12, 31), Value = 540 },
};
var result = list
.GroupBy(x => x.Date.Year)
.Select(g => new { Date = g.Key, MaxValue = g.Max(x => x.Value) });
foreach (var item in result)
{
Console.WriteLine(item);
}
}
}