How to get Dapper to ignore/remove underscores in field names when mapping? - postgresql

There are many ways to map database field names to class names, but what is the simplest way to just remove the underscores?
public IEnumerable<PersonResult> GetPerson(int personId)
{
using (var dbConnection = _dbConnectionFactory.Create(ConnectionStrings.ProjectXYZ))
{
IEnumerable<PersonResult> result =
dbConnection.Query<PersonResult>("fn_get_person", new { personId },
commandType: CommandType.StoredProcedure).ToList();
return result;
}
}
Table and database fields:
person
--------
person_id
full_name
Class that works: (dapper already ignores capitalization)
public class PersonResult
{
public int Person_Id { get; set; }
public string Full_Name { get; set; }
}
What I would like to change the class to:
public class PersonResult
{
public int PersonId { get; set; }
public string FullName { get; set; }
}

Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
job done ;p

The readme doesn't show any support for renaming columns. You could alias them in select:
select person_id as personid, full_name as fullname from fn_get_person();
as suggested in this answer.

Related

Adding Entity with complex type property

I am trying to add the student entity in my database, which looks like this:
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public Course Course { get; set; }
}
The Course class looks like this:
public class Course
{
public int ID { get; set; }
public string Name { get; set; }
}
Data in the Course table:
| ID | Course |
------------------------
| 1 | Math |
-----------------------
| 2 | Physics |
-----------------------
When I define student as shown below:
var student = new Student
{
Name = "ABC",
Course = new Course { ID = 1, Name = "Math"}
};
and try to add it so
context.Students.add(student);
await context.SaveChangesAsync()
the entity wasn't added. I added this line of code
context.Entry(student).State = EntityState.Added;
but nothing changed.
First of all you have to set Foreign Key CourseId to your Student entity.
A) Student Entity
public class Student
{
public int StudentID { get; set; }
public string Name { get; set; }
public int CourseID { get; set; } //This is foreign key
public virtual Course Course { get; set; }
}
B) Course Entity: ICollection property gives you all students with particular CourseID.
public class Course
{
public int CourseID { get; set; }
public string Name { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
1) If you add new student record with new course then
Course course = new Course
{
Name = "Math"
};
Course insertedCourse = context.Courses.Add(course);
Student student = new Student
{
CourseID = insertedCourse.CourseID,
Name = "ABC"
};
context.Students.Add(student);
await context.SaveChangesAsync();
2) If you have to reference your existing course from database then you have to get course from database and assign courseId to student entity.
Course existingCourse = GetCourseByIdFromDatabase();
Student student = new Student
{
CourseID = existingCourse.CourseID, //This ID comes from Db
Name = "ABC"
};
context.Students.Add(student);
await context.SaveChangesAsync();
Try once may it help you.
Edited:
As I understood with your last comment,
If you want to get student with its corresponding course then
Your get student method look like
public Student GetStudent(int Id)
{
Student student = context.Students.Find(Id);
return new Student
{
StudentID = student.StudentID,
Name = student.Name,
Course = student.Course
};
}
Ad you can access student's course like
Student student = GetStudent(1);
string CourseName = student.Course.Name;
you can use your async and await with above code depending your need.

NOT IN filter in a query with a join of two collections using MongDB C# driver

I have two collections that can be modelled with these classes (simplified version):
public class Profile
{
[BsonId]
[BsonRepresentation(BsonType.String)]
public Guid? Id { get; set; }
public string Name { get; set; }
[BsonRepresentation(BsonType.String)]
public Guid UserId { get; set; }
}
public class User
{
[BsonId]
[BsonRepresentation(BsonType.String)]
public Guid? Id { get; set; }
public string UserName { get; set; }
public bool IsConfirmed { get; set; }
}
I need a query to get all the UserProfiles whose User has the IsConfirmed flag equals true, and then I need to filter out the ones whose Id is included in a list of excluded Ids:
IList<Guid> profileIdsToExclude
This is the query I've built so far:
var professionalProfilesQuery =
(from profileCollection in _mongoContext.Database.GetCollection<Profile>("profiles").AsQueryable()
join userCollection in _mongoContext.Database.GetCollection<User>("users").AsQueryable()
on profileCollection.UserId equals userCollection.Id.Value
into users
orderby profileCollection.Name
select new ProfessionalProfile
{
Id = profileCollection.Id,
Name = profileCollection.Name,
UserId = profileCollection.UserId,
IsConfirmed = users.First().IsConfirmed,
})
.Where(p => p.IsConfirmed && !profileIdsToExclude.Contains(p.Id.Value));
Where ProfessionalProfile is a class to return the query result:
public class ProfessionalProfile
{
public Guid? Id { get; set; }
public string Name { get; set; }
public Guid UserId { get; set; }
public bool IsConfirmed { get; set; }
}
I get UserProfiles, only the ones with IsConfirmed equals true. But the ones whose Id is in the list of excluded Ids are not filtered out and are returned by the query.
Any idea if what I want to do is possible and how?
Thanks in advance.
Your problem here is caused by a little type confusion.
The query that the driver creates contains a $match stage at the end that looks kind of like this:
{
$match: {
IsConfirmed: true,
Id: {
$nin: [ BinData(3, "DBA38D51FC28094BA2D6439E95643A49") ]
}
}
}
So it is actually trying to exclude results that have a field with a particular Guid value. You are, however, storing strings for your Guids so the filter does not exclude anything. In order to fix that here is what you could do:
Change
.Where(p => p.IsConfirmed && !profileIdsToExclude.Contains(p.Id.Value));
into
.Where(p => p.IsConfirmed && !profileIdsToExclude.Contains(p.Id));
and
IList<Guid> profileIdsToExclude
into
IList<Guid?> profileIdsToExclude

Entity Framework Code First Query with Dynamic Table Name

I use entity framework code first.Is it possible to give table name dynamically in query phase.I want to pass table name to mymethod and set table name dynamically.
I can use like this.
[Table("MY_MESSAGE", Schema = "MySchema")]
public class MyMessage
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public string REQUESTID { get; set; }
public string BAG { get; set; }
}
public DbSet<MyMessagee> SET_TBL_MYMESSAGE { get; set; }
public MyMessage GetMessageByRequestID(string TableName, string RequestID)
{
using (HandlerDatabaseContext dbContext = HandlerDatabaseContext.CreateContext())
{
var handlerQuery = from table in dbContext.SET_TBL_MYMESSAGE
where table.REQUESTID == RequestID
select table;
...
}

Entity framework 6 use parentid in where clause with lambda expression

I'm new to EF and want to get an entry from my database (SQLite) in the following way:
Classes:
public class Customer
{
public Guid Id { get; set; }
public List<Month> Months { get; } = new List<Month>();
}
public class Month
{
public int Id { get; set; }
public string CacheId { get; set; }
public string Data { get; set; }
[Required]
public Customer Customer { get; set; }
}
DBContext:
public DbSet<Customer> Customers { get; set; }
public DbSet<Month> Months { get; set; }
Usage:
using (var context = new CustomerContext())
{
var customer = context.Customers.First();
context.Database.Log = Console.WriteLine;
var shouldContainOneEntry = context.Months.Where(x => x.Customer.Id == customer.Id).ToList();
}
shouldContainOneEntry is emtpy, but a test with a delegate and a static variable instead of the lambda expression worked:
private static Guid staticGuid;
public static bool DelegateTest(Month x)
{
return staticGuid == x.Customer.Id;
}
...
staticGuid = customer.Id;
var workingVersion = context.Months.Where(DelegateTest).ToList();
The generated SQL looks correct:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[CacheId] AS [CacheId],
[Extent1].[Data] AS [Data],
[Extent1].[Customer_Id] AS [Customer_Id]
FROM [Months] AS [Extent1]
WHERE [Extent1].[Customer_Id] = #p__linq__0
-- p__linq__0: '5cfde6e0-5b3f-437b-84c8-2845b077462d' (Type = AnsiStringFixedLength, IsNullable = false)
Why is the version with the lambda expression not working?
The solution was found by following the hints of IvanStoev.
SQLite stores the Guid by default in a binary format.
Therefor a query like
SELECT * FROM Months WHERE CustomerId = '5cfde6e0-5b3f-437b-84c8-2845b077462d'
delivers an empty result.
Using SQLite Adminstrator the Guid is shown with the binary format.
Using the server explorer in VS the Guid is shown with a string format which lead me to the wrong conclusion that this should work.
After setting the option BinaryGUID of the connection string to false the code works fine.
Based on your declarations
public class Customer
{
public Guid Id { get; set; }
public List<Month> Months { get; } = new List<Month>();
}
public class Month
{
public int Id { get; set; }
public Guid CustomerId{get;set;} // you need to add the foreign Key of the customer ( i will suppose that your foreign key in db called CustomerId
public string CacheId { get; set; }
public string Data { get; set; }
[Required]
[ForeignKey("CustomerId")] // and you need to tell EF which column is the foreign key
public Customer Customer { get; set; }
}
how to use it now
using (var context = new CustomerContext())
{
var customer = context.Customers.First();
context.Database.Log = Console.WriteLine;
var shouldContainOneEntry = context.Months.Where(x => x.CustomerId == customer.Id).ToList();
}
hope it will help you

Difficulties while querying with LINQ Many to Many (MTM) association

IMHO, I think this is the hardest thing for me to get - the whole MTM side of LINQ and I need help.
In SQL I have 3 tables: Accounts, AccountsInFeatures and Features. AccountsInFeatures simply has two primary key columns that link to Accounts to Features.
In EF, AccountsInFeatures is not visible - I understand why - but I'm having problems creating the LINQ:
Here's what I'm trying to do:
return (from a in _Store.Accounts
where a.AccountGUID == _AccountGUID
select new AccountDetails
{
AccountGUID = a.AccountGUID
AccountName = a.AccountName,
SelectedFeatures = a.Features.Select(f => f.FeatureGUID).ToList()
}).ToList();
Here's the definition for AccountDetails:
public class AccountDetails
{
public Guid AccountGUID { get; set; }
public string AccountName { get; set; }
public List<Guid> SelectedFeatures { get; set; }
}
How do I fill "SelectedFeatures" with a list of Features - is this possible? I'm close to just splitting this into two queries =)
Do this:
public class AccountDetails
{
public Guid AccountGUID { get; set; }
public string AccountName { get; set; }
public Collection<Features> SelectedFeatures { get; set; }
}
and
return (from a in _Store.Accounts
where a.AccountGUID == _AccountGUID
select new AccountDetails
{
AccountGUID = a.AccountGUID
AccountName = a.AccountName,
SelectedFeatures = a.Features
}).ToList();