How can i join between two table in LiteDb Like SQL
Example : I Have Two table User and ActivityLog
Here is the Model
public class ActivityLog
{
[BsonId]
public int Id { get; set; }
public string UserId { get; set; }
public string Action { get; set; }
public DateTime ActionDateTime { get; set; }
}
public class User
{
[BsonId]
public int Id { get; set; }
public string UserId { get; set; }
public string UserName { get; set; }
public DateTime LoginDate { get; set; }
}
I need to join Activity.UserID = User.UserId.
Is there any way to join like sql
From official documentation
LiteDB is a document database, so there is no JOIN between
collections. If you need reference a document in another document you
can use DbRef. This document reference can be loaded when the
database is initialized or when a query is run, or after a query is
finished.
In your case, you can do smth like
public class ActivityLog
{
[BsonId]
public int Id { get; set; }
public DbRef<User> User { get; set; }
public string Action { get; set; }
public DateTime ActionDateTime { get; set; }
}
public class User
{
[BsonId]
public int Id { get; set; }
public string UserId { get; set; }
public string UserName { get; set; }
public DateTime LoginDate { get; set; }
}
//usage
// Getting user and activityLog collections
var usersCollection = db.GetCollection<User>("Users");
var activityLogsCollection = db.GetCollection<ActivityLog>("ActivityLogs");
// Creating a new User instance
var user = new User { UserId = 5, ...};
usersCollection.Insert(user);
// Create a instance of ActivityLog and reference to User John
var activityLog = new ActivityLog
{
OrderNumber = 1,
OrderDate = DateTime.Now,
//Add it by DbRef
User = new DbRef<User>(usersCollection, user.UserId)
};
activityLogsCollection.Insert(activityLog)
See the documentation for more details.
Related
I have two tables with a many-to-many relationship and a link table. One is called taskSchedule and the other is called User. They are linked through a table called UserTask. One user can have many tasks assigned to them and one task can have many users assigned to them. I have run the dotnet ef database update command and it has successfully created the link table userTasks in the mysql database.
However, I am trying to get one of the APIs to post information to the taskSchedule table where it needs to add the user id and task id to the userTask link table. However I have no idea on how to do this.
below is the model for user.cs, taskschedule.cs and userTask.cs
user.cs
public class User: IdentityUser<int>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<UserRole> UserRoles {get; set;}
public IList<userTask> UserTasks {get; set;}
}
TaskSchedule.cs
public class TaskSchedule
{
public int Id { get; set; }
public string Title { get; set; }
public DateTime? Start { get; set; }
public DateTime? End { get; set; }
public bool isClosed { get; set; }
public bool isDeleted { get; set; }
public byte priorityLevel { get; set; }
public bool hasTimeLimit { get; set; }
public Customer customer { get; set; }
public int? customerId { get; set; }
public List<Note> Notes { get; set; }
public List<AttachmentFile> Attachments { get; set; }
//user currently assigned to the task
// public int? userCurrentAssignedId { get; set; }
// [ForeignKey("userCurrentAssignedId")]
// public User userCurrentAssigned { get; set; }
public List<userTask> UserTasks {get; set;}
//user who last edited the task
public int? userLastEditId { get; set; }
[ForeignKey("userLastEditId")]
public User userLastEdit { get; set; }
public DateTime? userLastEditDate { get; set; }
public DateTime taskCreatedDate { get; set; }
}
}
userTask.cs // linktable
public class userTask
{
public int UserId { get; set; }
public User User { get; set; }
public int TaskScheduleId { get; set; }
public TaskSchedule TaskSchedule { get; set; }
}
Controller to update record
[HttpPut("{id}")]
public ActionResult<TaskSchedule> PutSchedule(int id, [FromBody] TaskSchedule taskSchedule)
{
int tokenUserId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);
taskSchedule.userLastEditId = tokenUserId;
DateTime thisDay = DateTime.Now;
string NowDate = thisDay.ToString("g");
taskSchedule.userLastEditDate = Convert.ToDateTime(NowDate);
if(taskSchedule.Start < taskSchedule.End || taskSchedule.Start == null && taskSchedule.End == null) {
TaskSchedule taskSchedulePut = _repo.Update(id, taskSchedule);
return taskSchedulePut;
}
return BadRequest("start time is not less than end time");
}
repository
public TaskSchedule Update(int Id, TaskSchedule taskSchedule)
{
var TaskScheduleDb = _context.TaskSchedules.SingleOrDefault(s => s.Id == Id);
TaskScheduleDb.Title = taskSchedule.Title;
TaskScheduleDb.Start = taskSchedule.Start;
TaskScheduleDb.End = taskSchedule.End;
TaskScheduleDb.userLastEditDate = taskSchedule.userLastEditDate;
// this is where the userId needs to be updated on the usertable.
taskSchedule.UserTasks.FirstOrDefault(u => u.UserId == taskSchedule.UserTasks.);
taskSchedule.UserTasks[0].UserId = taskSchedule.UserTasks.;
_context.SaveChanges();
return TaskScheduleDb;
}
Where in the repository can I add the tokenUserId, coming from the controller, to the userId in the userTask link table? Furthermore, how do I add the taskId for the userTask link table if the taskId is only just being generated?
I don't see why you need to update UserTask table too. So just replace
taskSchedule.UserTasks.FirstOrDefault(u => u.UserId == taskSchedule.UserTasks.);
taskSchedule.UserTasks[0].UserId = taskSchedule.UserTasks.;
_context.SaveChanges();
with
_context.Entry(TaskScheduleDb).State=EntityState.Modified;
_context.SaveChanges();
I'm trying to convert a SQL statement into LINQ.
I have these models:
public class GamesNight
{
public int id { get; set; }
[DisplayName("Games Night Official Name")]
public string EventName { get; set; }
[DisplayName("Description")]
public string EventDescription { get; set; }
[DisplayName("Date and Time")]
[DataType(DataType.Date)]
public DateTime DateTime { get; set; }
public virtual ApplicationUser User { get; set; }
public bool Active { get; set; }
}
and a GamesNightAttendance, this is more or less linking a user to a games night event.
public class GamesNightAttendance
{
[Key]
public int id { get; set; }
public virtual GamesNight GameNight { get; set; }
public virtual ApplicationUser UserName { get; set; }
public bool Attendance { get; set; }
}
so a user hosts a GamesNight then other users will be able to attend the games night via the gamesnightattendancemodel.
The query I have is:
var userID = User.Identity.GetUserId();
var user = db.Users.First(x => x.Id == userID);
var result = from GNS in db.GamesNights
join GNA in db.GamesNightAttendance on GNS.id equals GNA.id
where GNS.Active & GNA.UserName == user
select new UpcomingGNAttendanceViewModel { GamesNight = GNS, Attendance = GNA.Attendance};
I get the exception:
Message = "Unable to create a constant value of type 'GNR.Models.ApplicationUser'. Only primitive types or enumeration types are supported in this context."
Your naming conventions don't help you:
public virtual ApplicationUser UserName { get; set; }
That's not a username, that's a user. That table is also missing a property to actually hold the relationship, as well as the property to hold the GameNight Id. The Attendance property also doesn't make a lot of sense, as there is no reason for you to create a GamesNightAttendance with Attendance = false.
That class should look more like this:
public class GamesNightAttendance
{
public int Id { get; set; }
// add missing foreign key
public int GameNightId { get; set; }
// add missing foreign key
public int UserId { get; set; }
public virtual GamesNight GameNight { get; set; }
// fix name
public virtual ApplicationUser User { get; set; }
}
With that model, you can now do this:
var userId = User.Identity.GetUserId();
var result =
from gameNight in db.GamesNights
join attendance in db.GamesNightAttendance on gameNight.Id equals attendance.Id
where gameNight.Active && attendance.UserId == userId
select new UpcomingGNAttendanceViewModel
{
GamesNight = gameNight,
Attendance = attendance
};
I have 2 entities being them: Employees and SendMessage:
public class Employee
{
[DbColumn(IsIdentity =true, IsPrimary =true)]
public long EmployeeId { get; set; }
[DbColumn]
public string Name { get; set; }
[DbColumn]
public string Surname { get; set; }
[DbColumn]
public string Date_Birth { get; set; }
[DbColumn]
public string Home_Address { get; set; }
[DbColumn]
public string City { get; set; }
[DbColumn]
public string Postcode { get; set; }
[DbColumn]
public string Telephone { get; set; }
[DbColumn]
public string Mobile { get; set; }
[DbColumn]
public string Email { get; set; }
[DbColumn]
public long ShiftId { get; set; }
}
As you can see the EmployeeId field is to connect the two
public class MessageSent
{
[DbColumn(IsIdentity =true, IsPrimary =true)]
public long MessageSentId { get; set; }
[DbColumn]
public long EmployeeId { get; set; }
[DbColumn]
public long MessageSentSeq { get; set; }
[DbColumn]
public string Status { get; set; }
[DbColumn]
public string DateSent { get; set; }
}
To redeem I use the following method
gvEmployee.DataSource = new EmployeeService().GetAll();
Now comes my need I need to show on my new screen the following fields:
MessageSentId,EmployeeId,MessageSentSeq of the table MessageSent and Name,Surname of the table Employees.
How can I create a third list with these 5 fields to fill my grid?
Take your employees:
var employees = new EmployeeService().GetAll();
Then your messages:
var messages = new MessageSentService().GetAll(); // probably like this, idk what its in your code
Using the LINQ query syntax is much clearer, more natural, and makes it easier to spot errors:
var query =
from employee in employees
join message in messages
on employee.EmployeeId equals message.EmployeeId
select new {
MessageSentId = message.MessageId,
EmployeeId = message.EmployeeId,
MessageSentSeq = message.MessageSentSeq,
Name = employee.Name,
Surname = employee.Surname
};
Then you can use query and its fields.
I've created a foreign key reference to the 'ApplicationUser' entity in my 'YogaSpace' entity seen below, but when I create a new YogaSpace and save it to the DB the column 'ApplicationUserRefId' is null? Shouldn't it contain the user id from application user without me inserting it into the entity before I save it? I know the answer would seem to be yes because I have another member in 'YogaSpace' called Images and it gets the 'YogaSpace' entity id automatically without me inserting it into the 'Images' entity before I save. So I don't have to insert the id there. How come it doesn't insert the user id with 'YogaSpace'?
public class YogaSpace
{
public int YogaSpaceId { get; set; }
public virtual ICollection<YogaSpaceImage> Images { get; set; }
[MaxLength(128)]
public string ApplicationUserRefId { get; set; }
[ForeignKey("ApplicationUserRefId")]
public virtual ApplicationUser ApplicationUser { get; set; }
}
public class ApplicationUser : IdentityUser
{
public DateTime MembershipCreated { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime? Birthdate { get; set; }
public Gender Gender { get; set; }
public virtual ICollection<YogaSpace> YogaSpaces { get; set; }
}
public class YogaSpaceImage
{
public int YogaSpaceImageId { get; set; }
public byte[] Image { get; set; }
public byte[] ImageThumbnail { get; set; }
public string ContentType { get; set; }
public int Ordering { get; set; }
[Index]
public int YogaSpaceRefId { get; set; }
[ForeignKey("YogaSpaceRefId")]
public virtual YogaSpace YogaSpace { get; set; }
}
Here is how I create a 'YogaSpace' entity. You can see I don't put anything into 'ApplicationUserRefId', BUT I expect it to autopopulate with user id from Application User, just like YogaSpacerefId gets auto populated when I create an image and save it.
var newSpace = new YogaSpace
{
Overview = new YogaSpaceOverview
{
Title = viewModel.Title,
Completed = ListingComplete.Incomplete
},
Listing = new YogaSpaceListing
{
Accommodation = (YogaSpaceAccommodation)viewModel.YogaSpaceAccommodation,
SpaceLocation = (YogaSpaceLocation)viewModel.YogaSpaceLocation,
SpaceType = (YogaSpaceType)viewModel.YogaSpaceType
},
Details = new YogaSpaceDetails
{
Completed = ListingComplete.Complete
},
Address = new YogaSpaceAddress
{
Completed = ListingComplete.Incomplete
},
DateCreated = DateTime.Now
};
yogaSpaceRepository.InsertOrUpdate(newSpace);
yogaSpaceRepository.Save();
Below is the Entity class
public partial class TestPlanViewModel
{
public TestPlanViewModel()
{
this.TestPlanTestPoints = new List<TestPlanTestPoint>();
}
public int TestPlanId { get; set; }
public string TestPlanName { get; set; }
public virtual IList<TestPlanTestPoint> TestPlanTestPoints { get; set; }
}
public class TestPlanTestPoint
{
public int OrganizationId { get; set; }
public int TestPlanId { get; set; }
public string TestPlanName { get; set; }
public int TestPlanVersion { get; set; }
public int TestPointId { get; set; }
public string TestPointName { get; set; }
}
I need to write a query where I need to get the collections from the dbContext like,
var query = (from tpm in TestPlanMaster
join tptp in TestPlanTestPoint on tpm.TestPlanId equals tptp.TestPlanId
join tmm in TestMethodMaster on tptp.TestMethodId equals tmm.TestMethodId
join tpma in TestPointMaster on tptp.TestPointId equals tpma.TestPointId
select new
{
//Plan Details
tpm.TestPlanId,
tpm.TestPlanName,
}).ToList().Select(x => new Entities.CustomEntities.TestPlanViewModel ====> Custom Entity
{
TestPlanId = x.TestPlanId,
TestPlanName = x.TestPlanName,
TestPlanTestPoints = ?????? ==> how to fill this collection
});
As shown above the TestPlanTestPoints is the IList collection object. I need to populate the data with the values from TestPlanTestPoint table.
Any suggestions?
Model
TestPlan
public partial class TestPlanMaster
{
[DataMember]
public int TestPlanId { get; set; }
[DataMember]
public short TestPlanVersion { get; set; }
[DataMember]
public int OrganizationId { get; set; }
[DataMember]
public short TestPlanTypeId { get; set; }
[DataMember]
public string TestPlanName { get; set; }
}
TestPlanTestPointMapping Model
public partial class TestPlanTestPointMapping
{
[DataMember]
public int OrganizationId { get; set; }
[DataMember]
public int TestPlanId { get; set; }
[DataMember]
public short TestPlanVersion { get; set; }
[DataMember]
public int TestPointId { get; set; }
}
You are thinking too much sql, think more linq. You want to select "tpm" items, so just write a select of those and select the new TestPlanViewModel and fill its properties and navigational properties.
I'm assuming you have a TestPlanTestPoints navigational property in your TestPlanMaster.
var q = (from tpm in TestPlanMaster
select new TestPlanViewModel
{
TestPlanId = tpm.TestPlanId,
TestPlanName = tpm.TestPlanName,
TestPlanPoints = TestPlanTestPoint.Where(pr => tpm.TestPlanId == pr.TestPlanId).Select(tptp => new TestPlanTestPoint()
{
// Fill properties here
}
}).ToList();