LINQ - update a field within where clause - linq

My object hierarchy is like this:
class Detail
{
public List<Row> Rows { get; set; }
}
class Row
{
public List<Column> Columns { get; set; }
}
class Column
{
public string Name { get; set; }
public bool IsUpdated { get; set; }
}
I want to set column.IsUpdated = true where column.Name = "id".
I am trying this, it doesn't work.
detail.Rows.ForEach(r => r.Columns.Where(c => c.Name.ToLower().Equals("id")).ToList<Column>().Select(c => c.IsUpdated = true));

The philosophy of LINQ is to not have side effects. That's why on purpose it does not make it easy for you to do this. You could do it either with a classic
var cols = details.Rows.SelectMany(r => r.Columns)
.Where(c => c.Name.ToLower().Equals("id"));
foreach(var col in cols) {
col.IsUpdated = true;
}
or by using List.ForEach, but in a different manner:
details.Rows.SelectMany(r => r.Columns)
.Where(c => c.Name.ToLower().Equals("id")).ToList()
.ForEach(c => { c.IsUpdated = true });

LINQ is really intended for querying data, not changing values within the data. If you want to make an entire new detail item, you could do that:
var newDetail = new Detail
{
Rows = detail.Rows.Select(r => new Row
{
Columns = r.Columns.Select(c => new Column { Name = c.Name, IsUpdated = c.Name.ToLower() == "id" ? true : c.IsUpdated }).ToList()
})
.ToList()
};
Note that the above would be cleaner, most likely, if you added constructors for your types, as well.
That being said, if you want to update it in place, like you were showing, I would just use loops:
foreach(var row in detail.Rows)
foreach(var col in row.Columns)
if (col.Name.ToLower() == "id")
col.IsUpdated = true;
I find that far easier to follow, especially in this case.

You shouldn't mutate all elements of a collection with LINQ (although it can be done, see this question). It's simpler and more readable to just use a vanilla foreach.
foreach (var row in detail.Rows)
foreach (var col in row.Columns)
if (c.Name.ToLower().Equals("id"))
c.IsUpdated = true;

I just got it to work like this. Is it inefficient? Instead of .Select I put .Any. It works, but I'm not sure if it's inefficient on a large data. If yes, I can go with one of the answers.
detail.Rows.ForEach(r => r.Columns.Where(c => c.Name.ToLower().Equals("id")).ToList<Column>().Any(c => c.IsUpdated = true));

Give this a try. This should update "IsUpdated" now with the same concept you were already trying to use.
detail.Rows.ForEach(r => r.Columns.Where(c => c.Name.ToLower().Equals("id")).ToList<Column>().Select(c => {c.IsUpdated = true; return c;}));

Related

EF Core Oracle NVARCHAR2 - Can't save cyrillic to db

When trying to keep the Cyrillic alphabet in the database, only inverted question marks are saved in the database.
The model looks like this
public class Roles {
public string Name { get; set; }
public string Appname { get; set; }
public string Description { get; set; }
}
Creating a context like this
modelBuilder.Entity<Roles>(entity =>
{
entity.HasKey(e => new { e.Name, e.Appname });
entity.ToTable("ROLES");
entity.HasIndex(e => new { e.Name, e.Appname })
.HasName("PK_ROLES")
.IsUnique();
entity.Property(e => e.Name)
.HasColumnName("NAME")
.HasMaxLength(100)
.IsUnicode(false);
entity.Property(e => e.Appname)
.HasColumnName("APPNAME")
.HasMaxLength(20)
.IsUnicode(false);
entity.Property(e => e.Description)
.HasColumnName("DESCRIPTION")
//.HasMaxLength(256)
//.IsUnicode(true);
.HasColumnType("NVARCHAR2(256)");
});
Tried and what is commented out and the next line
The table looks created correctly
And the execution of this code
using (var context = new FrontContext())
{
var roles = context.Roles.ToList();
var role = new Roles{
Name = $"ADMINS{DateTime.Now.ToString("HHmmss")}",
Appname = "TESTAPP",
Description = "тестовая роль"};
context.Add(role);
context.SaveChanges();
}
...gives such a picture
Check thread:4291600#Oracle, they fixed it.
Just update Oracle.EntityFrameworkCore to 2.19.80 then you are good to go.
Remove .IsUnicode(false);
Ref:
https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.metadata.builders.propertybuilder-1.isunicode?view=efcore-5.0

codeigniter join table ss

I have a problem with codeigniter,
I want to do a join in the addition of a carrier,
when I add I assign a truck this driver
I want the state of truck changes from 0 to 1,
but I do not know,
public function add($email, $password , $nom , $prenom , $telephone,$id_camion)
{
$query = $this->db->get_where('transporteur', array('email' => $email));
if ($query->num_rows == 1) {
return FALSE;
}
$this->db->insert('transporteur', array('email' => $email,'password' => md5($password),'nom' => $nom ,'prenom'=>$prenom ,'telephone' => $telephone,'id_camion' => $id_camion));
return TRUE;
}
If I understand your question correctly, now that you've inserted a new carrier you want to set some state in a table of trucks. You already have the truck ID as a parameter so in theory all you need to do is:
//update only on a given camion_id
$this->db->where('id', $camion_id);
$this->db->update('camions', array('state' => 1));
Here I assume your table is called camions, its ID is id and the state column you're trying to change from 0 to 1 is called state.
If that's not quite right, please update your question. If you have trouble translating it into english, I can help with that, too. ;)
I'm confused about your question but you have (num_rows should be num_rows()) following code:
if ($query->num_rows == 1) {
return FALSE;
}
It should be:
if ($query->num_rows() == 1) {
return FALSE;
}
It's a method not a property. You may also use it like this way:
if ($query->num_rows()) {
return FALSE;
}

How to cast to a generic list from the lambda expression result

I have a class structure like below.
ObservableCollection<Group> deviceCollection = new ObservableCollection<Group>();
public class Group
{
public string Name { get; set; }
public List<TargetSelectionStructure> TargetCollection { get; set; }
}
public class TargetSelectionStructure
{
public string ItemId { get; set; }
public string Name { get; set; }
public bool IsGroup { get; set; }
}
From the observable collection object deviceCollection. I need to get the collection which matches with IsGroup property as false. So I have written like
var currentStruct = deviceCollection.Where(d => d.TargetCollection.Any(t => t.IsGroup == false));
Now the currentStruct should contain the collection basically List<TargetSelectionStructure>. I am unable to cast the currentStruct to the type of List<TargetSelectionStructure>.
How can I solve this?
You can't cast it, because currentStruct is an IEnumerable<Group>.
I think you query needs to look like this:
var currentStruct = deviceCollection.SelectMany(x => x.TargetCollection)
.Where(x => !x.IsGroup).ToList();
This returns all TargetSelectionStructure instances from all Groups that have IsGroup == false.
Your question is not entirely clear. It is possible to interpret your question in a second way: You want to have all TargetSelectionStructure instances from a Group if at least one of them has IsGroup == false.
To achieve this, you would use this query:
var currentStruct = deviceCollection.Where(x => x.TargetCollection
.Any(y => !y.IsGroup))
.SelectMany(x => x.TargetCollection)
.ToList();

Telerik MVC Grid: Collection Inside Column

I am using Telerik's MVC Grid in my project which really is good. Unfortunately I am stuck at last.. The problem is that I want to show a collection inside a column. The collection is a property of my user model. Here is the sample code:
{...}
.Columns(columns =>
{
columns.Bound(u => u.Id).Title("No.").Width(100);
columns.Bound(u => u.UserName).Title("User Name");
columns.Bound(u => u.CompanyName).Title("Company Adı");
columns.Template(u =>
{
foreach(var item in u.Roles)
{
}
}).Title("Roller");
columns.Command(commands =>
{
commands.Custom("viewDetails")
.Text("Detail")
.DataRouteValues(route => route.Add(o => o.Id).RouteKey("UserAccountId"))
.Ajax(false)
.Action("UserAccountRead", "Account");
commands.Delete().ButtonType(GridButtonType.ImageAndText);
})
.Width(200);
})
.Sortable()
.Pageable(paging => paging.PageSize(10))
.Localizable("en-EN")
)
{...}
In the foreach loop I've tried many things to display user roles, but haven't succeed.
#item.Name
I Got : Error: Only assignment, call, increment, decrement and new object expressions can be used as a statement
#:<text>#item.Name</text>
I Got: ; required
And so on... What should I write as a statement for just making the column to show user roles?
You can add a ReadOnly property to your model which returns a simplified formatted text for you. for example you :
partial class MyModel{
public string RolesAsString
{
get{
string result="";
foreach(var item in this.Roles)
{
result += string.format("{0},",item);
}
return result.trim(",");
}
}
}

NHIbernate (3.1) - Linq group by then order by count issue

I am trying to get a group by followed by an order by count to work but I keep getting a 'Antlr.Runtime.NoViableAltException' being thrown.
Here is the simplest error case I can create.
var results = ArticleStatsRepository.GetAll().GroupBy(x => x.Article.ArticleId)
.OrderBy(x => x.Count());
ArticleStatsRepository.GetAll() returns an IQueryable of ArticleStats.
public class ArticleStats
{
public virtual int ArticleStatsId { get; set; }
public virtual Article Article { get; set; }
public virtual User Viewer { get; set; }
public virtual ArticleStatTypeEN ArticleStatType { get; set; }
public virtual DateTime DateTime { get; set; }
}
Ultimately I would like the following query to execute.
return ArticleStatsRepository.GetAll()
.Where(x => x.DateTime > DateTime.Now.Add(-timeSpan))
.Where(x => x.ArticleStatType == ArticleStatTypeEN.View)
.GroupBy(x => x.Article.ArticleId)
.Select(x => new { ArticleId = x.Key, Count = x.Count() })
.OrderByDescending(x => x.Count)
.Join(ArticleRepository.GetAll(), artStats => artStats.ArticleId, articles => articles.ArticleId, (artStats, articles) => new MostPopularArticleResult { ArticleId = artStats.ArticleId, ArticleTitle = articles.Content.Title, Count = artStats.Count });
I am using Fluent NHibernate 1.2.0.712 which references NHibernate: 3.1.0.4000.
Any help would be greatly appreciated!
Regards
Steve
Update: This is how I got round the issue. Not perfect as I didn't want to start using HQL with its QueryOver and would of liked to stick to IQueryable throughout.
public virtual IQueryable<MostPopularArticleResult> GetMostPopularArticleResults(TimeSpan timeSpan, IQueryable<Article> filteredArticles, List<ArticleStatTypeEN> types, int take)
{
var results = ArticleStatsRepository.GetAllQueryOver().Where(x => x.DateTime > DateTime.Now.Add(-timeSpan));
results = results.Where(x => x.ArticleStatType.IsIn(types));
var articleIdsWithCounts = results.Select(
Projections.Group<ArticleStats>(x => x.Article.ArticleId),
Projections.Count<ArticleStats>(x => x.Article.ArticleId))
.OrderBy(Projections.Count<ArticleStats>(x => x.Article.ArticleId))
.Desc
.Take(take)
.List<object[]>()
.Select(x => new { ArticleId = (int)x[0], Count = (int)x[1] });
return articleIdsWithCounts.Join(filteredArticles, artStats => artStats.ArticleId, articles => articles.ArticleId, (artStats, articles) => new MostPopularArticleResult { ArticleId = artStats.ArticleId, ArticleTitle = articles.Content.Title, Count = artStats.Count })
.AsQueryable();
}
As #mynkow and #Chris S said that was a NH 3.1 issue. You could update library version or look at thoose question about simila problem:
http://sourceforge.net/p/nhibernate/mailman/nhibernate-issues/
Nhibernate 3 Linq throws Antlr.Runtime.NoViableAltException
NHibernate Query, using OfType and Subqueries
NHibernate 3.1 migration problem with Linq

Resources