LINQ & Entity Framework : issue with concatenating NULL value - linq

I have an INT fields called TradeNo that may contain NULL value. The requirement is to display on the dropdown the "contract Id" and the "trade no" in bracket and if "trade no" is null, then display N/A.
Example:
44444 (2222)
55555 ( N/A )
Here’s what I thought would work. This is my functions that returns a SelectList
public IEnumerable<SelectListItem> GetContractsBySupplierDropDown(string supplier)
{
var result = from c in context.Contracts
where c.Supplier==supplier
orderby c.ContractID
select new {
Text = c.ContractID.ToString() + " (" +
(c.TradeNo.HasValue ?
c.TradeNo.Value.ToString() :
" N/A ").ToString() +
" )",
Value = c.ContractID };
return new SelectList(result, "Text", "Value");
}
The error being return is:
LINQ to Entities does not recognize the method 'System.String ToString()'
method, and this method cannot be translated into a store expression.
From what I can tell, the error displayed means that EF is trying to convert ToString to a database function?

Unfortunately you cannot use ToString in a number field coming from the database.
As a work around you can cast ToList before doing it, so then the contents are in the memory.
public IEnumerable<SelectListItem> GetContractsBySupplierDropDown(string supplier)
{
var query = from c in context.Contracts
where c.Supplier==supplier
orderby c.ContractID
select new {
c.ContractID,
c.TradeNo,
};
var result = from c in query.ToList()
select new {
Text = c.ContractID.ToString() + " (" +
(c.TradeNo.HasValue ?
c.TradeNo.Value.ToString() :
" N/A ") +
" )",
Value = c.ContractID
};
return new SelectList(result, "Text", "Value");
}

Related

Adding parameters optionally to Spring Data JPA Native query

I am using Spring Data JPA with native queries like below
public interface ItemRepository extends JpaRepository<ItemEntity, Long> {
#Query(value = "select * from items i where i.category = :itemCategory and i.item_code = :itemCode", nativeQuery = true)
Page<ItemEntity> search(#Param("itemCategory") String itemCategory, #Param("itemCode") String itemCode, Pageable pageable);
}
Now, my use case is
It itemCode is available, only the item with that code from that category should be returned.
But if itemCode is not available then all items in that category should be returned.
So the problem with the above category is when itemCode is passed as NULL no data is returned since it does not match anything. whereas the requirement is it should be ignored.
So is there a way to optionally add a clause to Spring Data JPA native query. I know it is possible with CriteriaQuery but can we do something similar for native queries?
Thanks
Yes, it's feasible with native query too. Very Good explanation here read this
#Approach1
#NamedQuery(name = "getUser", query = "select u from User u"
+ " where (:id is null or u.id = :id)"
+ " And :username"
:itemCode is null or i.item_code = :itemCode
#Approach2
# UserDao.java
public User getUser(Long id, String usename) {
String getUser = "select u from user u where u.id " + Dao.isNull(id)
+ " And u.username " + Dao.isNull(username);
Query query = Dao.entityManager.createQuery(getUser);
}
# Dao.java
public static String isNull(Object field) {
if (field != null) {
if (field instanceof String) {
return " = " + "'" + field + "'";
} else {
return " = " + field;
}
} else {
return " is NULL ";
}
}
How to handle null value of number type in JPA named query
Just modify the where condition
i.item_code = :itemCode
to
:itemCode is null or i.item_code = :itemCode

Spring Data JPA Query by Example with access to nested Objects Attributes

I use Query by Example and want to know how I can find objects with certain properties in the nested objects.
A plan anyone?
Here is my example Code:
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher("offer2product.id.productId", match -> match.exact()
);
Offer2ProductId id = new Offer2ProductId();
id.setProductId(1337L);
Offer2Product offer2Product = new Offer2Product();
offer2Product.setId(id);
Set<Offer2Product> offer2productSet = new HashSet<>();
offer2productSet.add(offer2Product);
Offer probe = new Offer();
probe.setOffer2productSet(offer2productSet);
Example<Offer> example = Example.of(probe, matcher);
List<Offer> offerList = offerRepository.findAll(example);
Quoting Spring data documentation: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#query-by-example
Currently, only SingularAttribute properties can be used for property matching.
In your example, you want to search by a property that is a Set<> (offer2productSet), which is a PluralAttribute - it is not possible to search by this field. It will be ignored when building a query, as can be seen here:
https://github.com/spring-projects/spring-data-jpa/blob/master/src/main/java/org/springframework/data/jpa/convert/QueryByExamplePredicateBuilder.java#L112
man actually can do it, follow the example below, where demand has a list of labels, I don't have time to explain everything but soon I'll update this post.
#Repository
#RequiredArgsConstructor
public class DemandaFilterRepository {
private final EntityManager entityManager;
public Page<Demanda> findAll(DemandaFilterDTO demandaFilter, Pageable pageable) {
String query = "select d from Demanda d where 1=1";
Map<String, Object> parameters = new HashMap<>();
if (demandaFilter.getId() != null) {
query += " and d.id = :id";
parameters.put("id", demandaFilter.getId());
}
if (!StringUtils.isEmpty(demandaFilter.getTenant())) {
query += " and upper(d.tenant) = upper(:tenant)";
parameters.put("tenant", demandaFilter.getTenant());
}
if (!StringUtils.isEmpty(demandaFilter.getAssunto())) {
query += " and upper(d.assunto) like upper(:assunto)";
parameters.put("assunto", "%" + demandaFilter.getAssunto() + "%");
}
if (!StringUtils.isEmpty(demandaFilter.getDescricao())) {
query += " and upper(d.descricao) like upper(:descricao)";
parameters.put("descricao", "%" + demandaFilter.getDescricao() + "%");
}
if (!StringUtils.isEmpty(demandaFilter.getEtiqueta())) {
query = query.replace("Demanda d", "Demanda d inner join d.etiquetas etiqueta");
query += " and upper(etiqueta.descricao) = upper(:etiqueta)";
parameters.put("etiqueta", demandaFilter.getEtiqueta());
}
if (!StringUtils.isEmpty(demandaFilter.getNomeDemandante())) {
query += " and upper(d.demandante.nome) like upper(:nomeDemandante)";
parameters.put("nomeDemandante", "%" + demandaFilter.getNomeDemandante() + "%" );
}
if (!StringUtils.isEmpty(demandaFilter.getDtInclusao())) {
query += " d.dtInclusao like :dtInclusao";
parameters.put("dtInclusao", "%" + demandaFilter.getDtInclusao() + "%");
}
query += " ORDER BY d.id DESC ";
TypedQuery<Demanda> typedQuery = entityManager.createQuery(query, Demanda.class)
.setMaxResults(pageable.getPageSize())
.setFirstResult(pageable.getPageNumber() * pageable.getPageSize());
parameters.forEach(typedQuery::setParameter);
return new PageImpl<>(typedQuery.getResultList());
}
}
this is a class for one of a small project that I'm working on ...

Database column data having linebreaks are ignored when retrieved from Hibernate?

A CLOB database column data has linebreaks :
When I retrieve it and display the data inside a html table cell then the linebreaks are ignored :
#Override
#Transactional
public String getPrevisionRessourceAutreForProduit(Objectif produit) {
String hql = "select to_char(r.ress_comment_1) " +
"from ressource r join type_ressource t on r.type_ress_code = t.type_ress_code " +
"left join objectif o on r.obj_code = o.obj_code " +
"where o.obj_code = " + produit.getCode().toString() + " and upper(t.type_ress_code) = 'AUT'";
Session sessionDynamic = Utils.createDynamicSession(env);
Query query = sessionDynamic.createSQLQuery(hql);
#SuppressWarnings("unchecked")
List<String> list = (List<String>) query.list();
sessionDynamic.close();
if (list.isEmpty())
return "";
else
return list.get(0) == null ? "" : list.get(0);
}
So how to fix it ?
I found the solution by enclosing the data inside the tags <pre>...</pre>

How to select an enum to a new list?

var menuQuery = repository.MenuMasters.OrderBy(c => c.Position).Select(c => new { ID = c.MenuMasterID, Position = (MenuItemPosition)c.Position + " - " + c.SitePage.Title });
ViewBag.ParentID = new SelectList(menuQuery, "ID", "Position", selectedParentId);
public int Position { get; set; }
public MenuItemPosition MenuPosition {
get { return (MenuItemPosition)Position; }
set { Position = (int)value; }
}
public enum MenuItemPosition {
Top = 1, Main = 2, Footer = 3
}
I got an error which said "Unable to cast the type 'Type Name' to type 'Type Name'. LINQ to Entities only supports casting Entity Data Model primitive types."
MenuItemPosition is "Enum", Title is "string"
How can I fix this? Many thanks~!
I think you need to add .ToList after OrderBy, as string concatenation is not supported with Linq to Entities.. So your query will look something like :
var menuQuery = repository.MenuMasters.OrderBy(c => c.Position).ToList().Select(c => new { ID = c.MenuMasterID, Position = ((MenuItemPosition)c.Position).convertToString() + " - " + c.SitePage.Title });
Try something like
var menuQuery = repository.MenuMasters.OrderBy(c => c.Position).Select(c => new { ID = c.MenuMasterID, Position = c.Position.ToString() + " - " + c.SitePage.Title });

How do I perform a distinct on a column I am selecting dynamically?

I am using dynamic linq and selecting a column dynamically. I need to do a distinct on this. How could I do this?
var qry = tbl.AsEnumerable().AsQueryable()
.Select("new(it[\"" + this.UniqueName + "\"]
.ToString() as " + this.UniqueName + ")");
Thanks.
Instead of using
as " + this.UniqueName + "
do
as someFixedColumnName
and run your Distinct() clause on that, using ordinary Linq.
Alternatively, you could try this extension method:
public static IQueryable DynamicDistinct(this IQueryable source)
{
if (source == null) throw new ArgumentNullException("source");
return source.Provider.CreateQuery(
Expression.Call(
typeof(Queryable), "Distinct",
new Type[] { source.ElementType },
source.Expression));
}

Resources