I am trying to add records from table position for positionName(s) to let user select a position for employee when editing.My last attempts is to add a navigation property like field in company model
public virtual ICollection<Position> Mpositions { get; set; }
But all I got so far is null ref exception or no element in viewModel with property "PositionName" ass per viewbag didn't bother using everybody keeps recommending to avoid it so not going to do so either.
public ActionResult Edit([Bind(Include = "CompanyID,CompanyName,EntityForm,Address,Dissolute,CreationDate,FiscaleYear,Description")] Company company)
{
var GlbUpdate = db.Companies.Include(c => c.Members).Include(p => p.Mpositions);
List<Company> mdlCompanies = new List<Company>();
foreach (var item in GlbUpdate)
{
if ((item.Mpositions==null) || (item.Mpositions.Count() == 0))
{
item.Mpositions = (ICollection<Position>)new SelectList(db.Positions.Except((IQueryable<Position>)db.Positions.Select(xk => xk.Members)), "PositionID", "PositionName");
}
mdlCompanies.Add(item);
//I tried first to edit the Mpositions property directly in gblUpdate
//item.Mpositions = (IEnumerable<Position>)db.Positions.Select(p => new SelectListItem { Value = p.PositionID.ToString(), Text = p.PositionName}) ;
//(ICollection<Position>)db.Positions.ToListAsync();
}
In the view I have this
List<SelectListItem> mPositionNames = new List<SelectListItem>();
#*#this yields no results if I try gettign it from the compani record itself it gives a logic error where all id match all positionNames impossible to select an item and only positions already registered are available on the dropDownlist*#
#{foreach (var item in Model.Mpositions)
{
mPositionNames.Add(new SelectListItem() { Text = item.PositionName, Value = item.PositionID.ToString(), Selected = (false) ? true : false });
#*#selected attribute set to false not an issue, no data to select from :p so far*#
}
}
#*#null exception(if i try to midify Mpositions directly in controler) here or empty list if modify it then put it with original query in a new list*#
<div class="SectionContainer R-sectionContainerData" id="MwrapperDataRight">
#Html.DropDownListFor(mpos => item.PositionID, (SelectList)Model.Mpositions)
</div>
All I want to do is pull the positions table to create a drop downList so users can change the position of an employee but since position has a 1>many relation with employee not companies it is not bound automatically by EF nor I seem to be able to use Include() to add it.
Your query for editing positions are complex. This query must edit person's info only. Using Edit action for formalizing position's edit are not correct.It's againts to Single Responsibility Principle. Use ViewComponents for this situation. Load positions separately from person info.
I found a suitable solution using a model that encapsulate the other entities then using Partialviews/RenderAction so each part handles one entity/operation.
In my C# application I use NHibernate to get all rooms from my database table 'room'.
using (ISession pSession = NHibernateHelper.OpenSession())
{
IList<Room> roomList = pSession.QueryOver<Room>().
Where(x => x.FloorID == 3).
.List();
}
The table 'room' and also my Mapping class (Room.cs) contains lets say the following properties:
roomID
hash
date
identifier
I have a DataGridView which should display my table entries from the database: the code is:
roomDataGridView.DataSource = roomList;
That works fine so far. But now I decide that I dont want to show all the properties from the Room class, I only want to display
roomID
identifier
I tried the following:
roomDataGridView.DataSource = listOfRoomPropertiesForCurrentFloor.Select(x => new {x.Identifier, x.RoomID });
Unfortunately this does not work...nothing gets printed in my DataGridView.
Question: How can I store all properties from the room table in my room model BUT ONLY show TWO of the four properties in the DataGridView?
Make sure your column names are defined in the DataGridView and create the object, basically assign the x.Identifier to the name "Identifier" so it can be picked up and call the ToList() function
roomDataGridView.DataSource = listOfRoomPropertiesForCurrentFloor
.Select(x => new {Identifier = x.Identifier, RoomID = x.RoomID }).ToList();
Expecting that DataGridView attribute AutoCreateColumns should be set to true. There are already answers:
c# Hide a property in datagridview with datasource
Is there an Attribute I can use in my class to tell DataGridView not to create a column for it when bound to a List
Extract:
Mark the property which should not be displayed with an attribute [Browsable(false)]
I currently have data in db table as follows:
Data in table
Desc Value
BNo 12
CNo Null
ANo 15
DNo Null
ENo 15
If ANo is blank i need to display BNo. If BNo is blank then display CNo on form. Once i found a non null value based on a defined priority order of DESC(In this case A-E), i need to exit my method. How can this be implemented,i can hard code desc names based on priority but it am looking to implement in a more optimized way. Any advices please.
SQL Server
select top 1 *
from MyTable
where Value is not null
order by [Desc]
MySQL:
select *
from MyTable
where `Value` is not null
order by `Desc`
limit 1
It sounds like you have the means to order the list, as you state "in a priority order". Not sure what this priority is but for the example let's assume it is in alphabetical order by "Desc". And let's also assume (for simplicity) that these values are in a dictionary. Given this you can write a Linq statement as such...
dict.OrderBy(o => o.Key).FirstOrDefault(d => d != null);
eg...
Dictionary<string,string> dict = new Dictionary<string,string>();
dict.Add("BNo", "12");
dict.Add("CNo", null);
dict.Add("ANo", null);
dict.Add("DNo", null);
dict.Add("ENo", "16");
Debug.WriteLine(dict.OrderBy(o => o.Key).FirstOrDefault(d => d.Value != null));
This will return the first non-null value. If all values are null then null is returned.
There may be some incorrect assumptions here but the OrderBy and FirstOrDefault should be able to be used in whatever manner necessary to achieve your goal. The only things that should need to change is the "o.Key" and "d.Value" to reference your actual properties.
For example, if this information is in a class such as this...
class Info
{
public string Desc { get; set; }
public int? Number { get; set; }
}
and you have a list of these such as...
List<Info> info = new List<Info>();
then you could write...
var returnValue = info.OrderBy(o => o.Desc).FirstOrDefault(d => d.Number.HasValue);
Are ANo, BNo, CNo, etc values of the Desc field in the table, or are Desc, ANo, BNo.. etc fields in the table. I get this doubt because you just that these are actually contact details.
If it is the first, RedFilter gave you an answer.
If it is the second, a dynamic query can be an option.
Just add the fields in the order of priority to an array, and iterate to build the query.
Lets say I query the database and load a list of items. Then I open one of the items in a detail view form, and instead of re-querying the item out of the database, I create an instance of the item from the datasource in the list.
Is there a way I can update the database record without fetching the record of the individual item?
Here is a sample how I am doing it now:
dataItem itemToUpdate = (from t in dataEntity.items
where t.id == id
select t).FirstOrDefault();
Then after pulling the record I update some values in the item and push the record back:
itemToUpdate.itemstatus = newStatus;
dataEntity.SaveChanges();
I would think there would be a better way to do this, any ideas?
You should use the Attach() method.
Attaching and Detaching Objects
You can also use direct SQL against the database using the context of the datastore. Example:
dataEntity.ExecuteStoreCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = 123 ");
For performance reasons, you may want to pass in variables instead of a single hard coded SQL string. This will allow SQL Server to cache the query and reuse with parameters. Example:
dataEntity.ExecuteStoreCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });
UPDATE - for EF 6.0
dataEntity.Database.ExecuteSqlCommand
("UPDATE items SET itemstatus = 'some status' WHERE id = {0}", new object[] { 123 });
The code:
ExampleEntity exampleEntity = dbcontext.ExampleEntities.Attach(new ExampleEntity { Id = 1 });
exampleEntity.ExampleProperty = "abc";
dbcontext.Entry<ExampleEntity>(exampleEntity).Property(ee => ee.ExampleProperty).IsModified = true;
dbcontext.Configuration.ValidateOnSaveEnabled = false;
dbcontext.SaveChanges();
The result TSQL:
exec sp_executesql N'UPDATE [dbo].[ExampleEntities]
SET [ExampleProperty ] = #0
WHERE ([Id] = #1)
',N'#0 nvarchar(32),#1 bigint',#0='abc',#1=1
Note:
The "IsModified = true" line, is needed because when you create the new ExampleEntity object (only with the Id property populated) all the other properties has their default values (0, null, etc). If you want to update the DB with a "default value", the change will not be detected by entity framework, and then DB will not be updated.
In example:
exampleEntity.ExampleProperty = null;
will not work without the line "IsModified = true", because the property ExampleProperty, is already null when you created the empty ExampleEntity object, you needs to say to EF that this column must be updated, and this is the purpose of this line.
If the DataItem has fields EF will pre-validate (like non-nullable fields), we'll have to disable that validation for this context:
DataItem itemToUpdate = new DataItem { Id = id, Itemstatus = newStatus };
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.Configuration.ValidateOnSaveEnabled = false;
dataEntity.SaveChanges();
//dataEntity.Configuration.ValidateOnSaveEnabled = true;
Otherwise we can try satisfy the pre-validation and still only update the single column:
DataItem itemToUpdate = new DataItem
{
Id = id,
Itemstatus = newStatus,
NonNullableColumn = "this value is disregarded - the db original will remain"
};
dataEntity.Entry(itemToUpdate).Property(x => x.Itemstatus).IsModified = true;
dataEntity.SaveChanges();
Assuming dataEntity is a System.Data.Entity.DbContext
You can verify the query generated by adding this to the DbContext:
/*dataEntity.*/Database.Log = m => System.Diagnostics.Debug.Write(m);
Now native support for this in EF Core 7 — ExecuteUpdate:
Finally! After a long wait, EF Core 7.0 now has a natively supported way to run UPDATE (and also DELETE) statements while also allowing you to use arbitrary LINQ queries (.Where(u => ...)), without having to first retrieve the relevant entities from the database: The new built-in method called ExecuteUpdate — see "What's new in EF Core 7.0?".
ExecuteUpdate is precisely meant for these kinds of scenarios, it can operate on any IQueryable instance, and lets you update specific columns on any number of rows, while always issuing a single UPDATE statement behind the scenes, making it as efficient as possible.
Usage:
Imagine you wanted to update the Email column of a specific user:
dbContext.Users
.Where(u => u.Id == someId)
.ExecuteUpdate(b =>
b.SetProperty(u => u.Email, "NewEmail#gmail.com")
);
As you can see, calling ExecuteUpdate requires you to make calls to the SetProperty method, to specify which property to update, and also what new value to assign to it.
EF Core will translate this into the following UPDATE statement:
UPDATE [u]
SET [u].[Email] = "NewEmail#gmail.com"
FROM [Users] AS [u]
WHERE [u].[Id] = someId
Also, ExecuteDelete for deleting rows:
There's also a counterpart to ExecuteUpdate called ExecuteDelete, which, as the name implies, can be used to delete a single or multiple rows at once without having to first fetch them.
Usage:
// Delete all users that haven't been active in 2022:
dbContext.Users
.Where(u => u.LastActiveAt.Year < 2022)
.ExecuteDelete();
Similar to ExecuteUpdate, ExecuteDelete will generate DELETE SQL statements behind the scenes — in this case, the following one:
DELETE FROM [u]
FROM [Users] AS [u]
WHERE DATEPART(year, [u].[LastActiveAt]) < 2022
Other notes:
Keep in mind that both ExecuteUpdate and ExecuteDelete are "terminating", meaning that the update/delete operation will take place as soon as you call the method. You're not supposed to call dbContext.SaveChanges() afterwards.
If you're curious about the SetProperty method, and you're confused as to why ExectueUpdate doesn't instead receive a member initialization expression (e.g. .ExecuteUpdate(new User { Email = "..." }), then refer to this comment (and the surrounding ones) on the GitHub issue for this feature.
Furthermore, if you're curious about the rationale behind the naming, and why the prefix Execute was picked (there were also other candidates), refer to this comment, and the preceding (rather long) conversation.
Both methods also have async equivalents, named ExecuteUpdateAsync, and ExecuteDeleteAsync respectively.
I recommend using Entity Framework Plus
Updating using Entity Framework Core can be very slow if you need to update hundreds or thousands of entities with the same expression. Entities are first loaded in the context before being updated which is very bad for the performance and then, they are updated one by one which makes the update operation even worse.
EF+ Batch Update updates multiple rows using an expression in a single database roundtrip and without loading entities in the context.
// using Z.EntityFramework.Plus; // Don't forget to include this.
// UPDATE all users inactive for 2 years
var date = DateTime.Now.AddYears(-2);
ctx.Users.Where(x => x.LastLoginDate < date)
.Update(x => new User() { IsSoftDeleted = 1 });
Simple and elegant extension method:
I've written an extension method for DbContext that does exactly what the OP asked for.
In addition to that, it only requires you to provide a member initialization expression (e.g. new User { ... }), and it then figures out on its own what properties you've changed, so you won't have to specify them by hand:
public static void UpdateEntity<TEntity>(
this DbContext context,
int id,
Expression<Func<TEntity>> updateExpression
) where TEntity : BaseEntity, new()
{
if (updateExpression.Body is not MemberInitExpression memberInitExpr)
throw new ArgumentException("The update expression should be a member initialization.");
TEntity entityToUpdate = updateExpression.Compile().Invoke();
entityToUpdate.Id = id;
context.Attach(entityToUpdate);
var updatedPropNames = memberInitExpr.Bindings.Select(b => b.Member.Name);
foreach (string propName in updatedPropNames)
context.Entry(entityToUpdate).Property(propName).IsModified = true;
}
You also need a BaseEntity class or interface that has your primary key in it, like:
public abstract class BaseEntity
{
public int Id { get; set; }
}
Usage:
Here's how you'd use the method:
dbContext.UpdateEntity(1234 /* <- this is the ID */, () => new User
{
Name = "New Name",
Email = "TheNewEmail#gmail.con",
});
dbContext.SaveChanges();
Nice and simple! :D
And here's the resulting SQL that gets generated by Entity Framework:
UPDATE [Users]
SET [Name] = #p0, [Email] = #p1
WHERE [Id] = #p2;
Limitation:
This method only allows you to update a single row using its primary key.
So, it doesn't work with .Where(...), IQueryable<...>, and so on. If you don't have the PK, or you want to bulk-update, then this wouldn't be your best option. In general, if you have more complex update operations, then I'd recommend you use Entity Framework Plus, or similar libraries.
It works somewhat different in EF Core:
There may be a faster way to do this in EF Core, but the following ensures an UPDATE without having to do a SELECT (tested with EF Core 2 and JET on the .NET Framework 4.6.2):
Ensure your model does not have IsRequired properties
Then use the following template (in VB.NET):
Using dbContext = new MyContext()
Dim bewegung = dbContext.MyTable.Attach(New MyTable())
bewegung.Entity.myKey = someKey
bewegung.Entity.myOtherField = "1"
dbContext.Entry(bewegung.Entity).State = EntityState.Modified
dbContext.Update(bewegung.Entity)
Dim BewegungenDescription = (From tp In dbContext.Model.GetEntityTypes() Where tp.ClrType.Name = "MyTable" Select tp).First()
For Each p In (From prop In BewegungenDescription.GetProperties() Select prop)
Dim pp = dbContext.Entry(bewegung.Entity).Property(p.Name)
pp.IsModified = False
Next
dbContext.Entry(bewegung.Entity).Property(Function(row) row.myOtherField).IsModified = True
dbContext.SaveChanges()
End Using
ef core 7 :
public async Task<int> Update(UpdateLevelVm vm)
{
return await _db.Levels.Where(l => l.Id == vm.LevelId)
.ExecuteUpdateAsync(u => u
.SetProperty(l => l.GradeId, vm.GradeId)
.SetProperty(l => l.Title, vm.Title)
);
}
this has worked for me in EF core 3.1
await _unitOfWork.Context.Database.ExecuteSqlRawAsync("UPDATE Student SET Age = 22 Where StudentId = 123");
Generally speaking, if you used Entity Framework to query all the items, and you saved the entity object, you can update the individual items in the entity object and call SaveChanges() when you are finished. For example:
var items = dataEntity.Include("items").items;
// For each one you want to change:
items.First(item => item.id == theIdYouWant).itemstatus = newStatus;
// After all changes:
dataEntity.SaveChanges();
The retrieval of the one item you want should not generate a new query.
with my Repository classes, I use LinqToSql to retrieve the data from the repository (eg. Sql Server 2008, in my example). I place the result data into a POCO object. Works great :)
Now, if my POCO object has a child property, (which is another POCO object or an IList), i'm trying to figure out a way to populate that data. I'm just not too sure how to do this.
Here's some sample code i have. Please note the last property I'm setting. It compiles, but it's not 'right'. It's not the POCO object instance .. and i'm not sure how to code that last line.
public IQueryable<GameFile> GetGameFiles(bool includeUserIdAccess)
{
return (from q in Database.Files
select new Core.GameFile
{
CheckedOn = q.CheckedOn.Value,
FileName = q.FileName,
GameFileId = q.FileId,
GameType = (Core.GameType)q.GameTypeId,
IsActive = q.IsActive,
LastFilePosition = q.LastFilePosition.Value,
UniqueName = q.UniqueName,
UpdatedOn = q.UpdatedOn.Value,
// Now any children....
// NOTE: I wish to create a POCO object
// that has an int UserId _and_ a string Name.
UserAccess = includeUserIdAccess ?
q.FileUserAccesses.Select(x => x.UserId).ToList() : null
});
}
Notes:
Database.Files => The File table.
Database.FilesUserAccess => the FilesUserAccess table .. which users have access to the GameFiles / Files table.
Update
I've now got a suggestion to extract the children results into their respective POCO classes, but this is what the Visual Studio Debugger is saying the class is :-
Why is it a System.Data.Linq.SqlClient.Implementation.ObjectMaterializer<..>
.Convert<Core.GameFile> and not a List<Core.GameFile> containing the POCO's?
Any suggestions what that is / what I've done wrong?
Update 2:
this is what i've done to extract the children data into their respective poco's..
// Now any children....
UserIdAccess = includeUserIdAccess ?
(from x in q.FileUserAccesses
select x.UserId).ToList() : null,
LogEntries = includeUserIdAccess ?
(from x in q.LogEntries
select new Core.LogEntry
{
ClientGuid = x.ClientGuid,
ClientIpAndPort = x.ClientIpAndPort,
// ... snip other properties
Violation = x.Violation
}).ToList() : null
I think that all you need to do is to put another Linq query in here:
q.FileUserAccesses.Select(x => x.UserId).ToList()
i.e. You want to select data from the FileUserAccess records - which I'm assuming are Linq to SQL classes, so to do this you can have something like:
(from fua in q.FileUserAccesses
select new PocoType
{
UserID = fua.UserID,
Name = fua.User.UserName // Not sure at this point where the name comes from
}).ToList()
That should get you pointed in the right direction at least.
What is the type of UserIdAccess? How is it not 'right'? Are you getting the 'wrong' data? if so have you checked your database directly to make sure the 'right' data is there?