EF Core query a postgreSQL user-defined enum type - postgresql

I have a column with a UDT in my table and when I try to query it with EF Core the database throws an error
operator does not exist: example_type = text
This doesn't work:
var type = ExampleType.ExampleValue;
query.Where(e => e.Type == type)...
But if I pass it directly it works
query.Where(e => e.Type == ExampleType.ExampleValue)...

Related

operator does not exist: json = json ef core

I am using efcore 5+ and Postgresql in my project , I have json property in my dataset as
[Column("servicesIncluded", TypeName ="json")]
public object ServicesIncluded { get; set; }
When I try to compare this value in join with some other table like:
var query = await (from costItemTemplate in _shipContext.CostItemTemplates
join itemDetails in _shipContext.CostTemplateDetails
on costItemTemplate.TemplateId equals itemDetails.CostItemTemplateId
where costItemTemplate.ShipmentType == quote.ShipmentType &&
costItemTemplate.TemplatePort.Contains(quote.FromLocation) &&
costItemTemplate.ServicesIncluded == quote.AdditionalService
select itemDetails).ToListAsync();
I get Error that operator does not exist: json = json
Npgsql.PostgresException (0x80004005): 42883: operator does not exist: json = json
I have tried to Serialize objects in ef core LINQ query but again that serialization is not supported in db .
Is there any way to compare these both (objects/json) columns?

The column was specified multiple times for 't'

Once I upgrade my entity framework core to the latest, I cannot execute below query.
enter image description here
var result = db.Actuacion.Where(m => m.ActId == id && m.TempSave != true).Include(m => m.Medico).Include(m=>m.Factura).FirstOrDefault();
Factura and Medico has the same column Name and then EF throw below exception to me
"The column 'PCIVA' was specified multiple times for 't'.
How can I get rid of this

How to convert IQueryable complex type to generic list in entity framework

IQueryable<SystemGroup> systemGroupQuery;
systemGroupQuery = dbContext.SystemGroups.Select(x => new SystemGroup()
{
Id = x.Id,
Name = x.Name,
SmsAccountId = x.SmsAccountId,
SmsAccount = dbContext.SmsAccounts.Where(g => g.Id
== x.SmsAccountId).SingleOrDefault()
});
var systemGroups = systemGroupQuery.ToList();
While converting to list i am getting the error "The entity or complex type 'Models.Context.SystemGroup' cannot be constructed in a LINQ to Entities query."
Add .ToList() before .Select
or
use anonymous object and map it after .ToList()
Linq to entities doesnt allow constructing complex typed objects in the fly

How to do a search with EF CodeFirst

Currently, to do a search using EF CodeFirst and a repository pattern, based on user input to multiple text boxes on an mvc search view/page, I do something like the following:
public PagedList<Entity1> PlayerUserSearch(Entity1SearchParameters searchParameters, int? pageSize, int? startEntity, Func<Entity1, object> sortOrder, bool sortDesc)
{
IQueryable<Entity1> query = from entities in this.DataContext.Entity1s.Include("Entity2List")
where entities.Entity2List.Any()
select entities;
if (searchParameters.Entity2PrimaryKeyId.HasValue)
query = query.Where(e => e.Id == searchParameters.Entity2PrimaryKeyId.Value);
if (searchParameters.HasStats.HasValue)
{
if (searchParameters.HasStats.Value)
query = query.Where(u => u.Entity2List.Any(e => e.Stat != null));
else
query = query.Where(u => u.Entity2List.Any(e => e.Stat == null));
}
if (searchParameters.Entity2OtherField.HasValue)
query = query.Where(u => u.Entity2List.Any(e => e.Event.Entity2OtherField == searchParameters.Entity2OtherField));
if (searchParameters.Entity2OtherField2.HasValue)
query = query.Where(u => u.Entity2List.Any(e => e.Event.Entity2OtherField2 == searchParameters.Entity2OtherField2));
if (searchParameters.Active.HasValue)
query = query.Where(e => e.Active == searchParameters.Active.Value);
return this.GetPageByStartEntity(pageSize.Value, startEntity.Value, query, sortOrder, sortDesc);
}
The problem with this is that for every time I add on another where that checks the child of Entity1 (Entity2) for a certain field, it takes on a new " AND EXISTS" clause to the sql statement generated, so that it is doing an exists and checking table Entity2 all over again for every different field checked, rather than doing a single EXISTS on Entity in the query, and checking all fields I tacked on to the query (i.e. EntityOtherField1 and EntityOtherField2). I haven't been able to find a better way to do a search based on user inputs than constantly checking for the input being there (add to the search parameters)) and then tacking on a new where to the current query. Can anyone tell me if there is a better way to do this? Thanks!
I think what you're looking for is using Specification Pattern.
var spec = new specification<Entity2>(s => true);
if (searchParameters.HasStats.Value)
{
spec = spec.And(e => e.Stat != null);
}
if (searchParameters.Entity2OtherField2.HasValue)
{
spec = spec.And(e => e.Event.Entity2OtherField2 == searchParameters.Entity2OtherField2);
}
query = query.Where(u => u.Entity2List.Any(spec));
Or I believe you can make it more standard by separating the filter logic and using spec.IsStatisfiedBy method.
A good framework for repository/specification implemetation on Entity Framework can be found here.

Why are anonymous Types in EF4 different from LINQ to SQL ones?

I have the following query in LINQ to SQL to fetch all records from a Table that are not already in a jointable.
// <param name="id">The ID of the Person</param>
IEnumberable<object> GetUnassignedClients(int id)
{
_db.Clients
.Select(i => new
{
Client_id = i.Id,
Person_id = id,
Cid = id + "." + i.Id // Please don't ask why I do this. I just have to do it
// ... some more fields
})
.Where(o =>
!_db.Clients_Persons
.Where(t => t.Person_id == id)
.Select(t => t.Client_id)
.Contains(o.Client_id))
.Distinct().ToList();
}
Now I have started a migration to EF4 but the "Cid" part of the anonymous type with the combination ToList() (ToList() triggered the exception is a simplified testcase without the WHERE condition) fails with the exception:
Unable to create a constant value of
type 'System.Object'. Only primitive
types ('such as Int32, String, and
Guid') are supported in this context.
Why is that so or am I missing something here?
EF does not know how to translate the expression id + "." + i.Id into valid SQL which is why it fails. You have to tell EF that it needs to convert id from an integer to a string. You can do this using the SqlFunctions class in the following way:
var ret = _db.Clients
.Select(i => new
{
Client_id = i.Id,
Person_id = id,
Cid = SqlFunctions.StringConvert((double) id) + "." + SqlFunctions.StringConvert((double) i.Id) // Please don't ask why I do this. I just have to do it
// ... some more fields
})
.Where(o =>
!_db.Clients_Persons
.Where(t => t.Person_id == id)
.Select(t => t.Client_id)
.Contains(id)
)
.Distinct()
.ToList()
;