I have a ListView which I filled in from SQL Server view called view_ListaKlientow with this query:
private void fillClientsList() {
using (var context = new EntityBazaCRM()) {
var listaKlientow = from d in context.view_ListaKlientow
select d;
objectListViewListaKlientow.SetObjects(listaKlientow.ToList());
objectListViewListaKlientow.AutoResizeColumns();
}
}
Then after user double clicks one row in ListView, I read ID from the view_ListaKlientow and use fillClientGui to fill necessary fields in gui (for a test only one field is included).
private void objectListViewListaKlientow_DoubleClick(object sender, EventArgs e) {
foreach (view_ListaKlientow user in objectListViewListaKlientow.SelectedObjects) {
int id = user.KlienciID;
fillClientGui(id);
TabPageActivate(tabControlMain, tabPageKlient);
}
}
private void fillClientGui(int klientId) {
using (var context = new EntityBazaCRM()) {
IQueryable<Klienci> klient = context.Kliencis.Include("Podmioty").Where(d => d.KlienciID == klientId);
foreach (var source in klient.ToList()) {
textNIP.Text = source.Podmioty.PodmiotNIP;
}
}
}
Now I'm wondering since I know exactly I'm querying for one ID i should be getting only particular client and not a list of clients so foreach from fillClientGui just to travers IQueryable<Klienci> seems like additional unnecessary code. Or this is how it should be done? I'm trying to learn Entity and some things aren't just clear to me yet :)
If you're sure that you've got only one instance to be returned form the database, you can use the extension function FirstOrDefault() in this case:
var source = context.Kliencis.Include("Podmioty").Where(d => d.KlienciID == klientId).FirstOrDefault();
textNIP.Text = source.Podmioty.PodmiotNIP;
Related
Using Visual Studio 2015 and learning ORM with SQlite + Entity (WPF application)
My database with fields: ID and ShipType
I can populate a listView with the ShypType field:
private void button_Click(object sender, RoutedEventArgs e)
{
List<string> shipList = new List<string>();
using (var db = new ImperialFleetDBEntities())
{
shipList = (from g in db.ShipsType select g.ShipType).ToList();
db.Dispose();
}
listView.Items.Clear();
foreach (string str in shipList)
{
listView.Items.Add(str);
}
}
But I can't figure how to also diplay the ID field (g.ID on this example)
In this link C# ListView Display the solution is using ListViewSubItems
But If I type listView. I don't have any SubItems option
The solution is 5 years old, maybe that's de problem??
The simplest way would probably be:
private void button_Click(object sender, RoutedEventArgs e)
{
using (var db = new ImperialFleetDBEntities())
{
listView.Items.Clear();
foreach(var item in (from g in db.ShipsType select new { ID = g.ID, ShipType = g.ShipType }))
{
listView.Items.Add(item)
}
}
}
This should populate your listView in correct way and make sure these new objects won't be tracked by EF.
If you'd like, you could create full class, like ViewModel for listView containing fields you need and then select to them like:
foreach(var item in (from g in db.ShipsType select new NewShipType { ID = g.ID, ShipType = g.ShipType }))
{
listView.Items.Add(item)
}
or using constructor (if you make one).
With seprate ViewModel you can of course use in-between list object and clear and add them to listView.Items, which is impossible with anonymous object.
By the way, you don't have, and maybe you shouldn't write db.Dispose() inside using clause, as using is exactly meant to make sure the object inside is disposed - you cannot use using on object that is not implementing IDisposable interface.
I have two tables, Equipment and Components. Each Equipment consists of 1 or more components. Right now I have a data grid showing the Equipment, with related attributes from a View in my database.
What I want is to have a second data grid in the same window, which will show the component the selected Equipment in the data grid contains.
So far I know that I can get a selected row using the SelectedItem property:
Equipment eq= (Equipment )myDataGrid.SelectedItem;
But when should this code be run? I am using EF to map my DB entities to CLR objects, where I have included the component and its relation table as well.
When the user selects a row in the Equipment, of course I would need to refresh the component data grid with the new info, which I can do like this.
myGrid.ItemsSource = myDataSource;
How can I get started on this problem?
I am using a view, that includes data from 3 different tables in my Equipment data grid, so the table set to the data grid ItemsSource does not have a direct relation with the component table.
I fixed it by using getting the components and inserted them into the data grid when the SelectionChanged event on the Equipment data grid is called:
private void EquipDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
var row_list = GetDataGridRows(EquipDataGrid);
foreach (DataGridRow single_row in row_list)
{
if (single_row.IsSelected == true)
{
EquipmentView selectedEquipment = (EquipmentView)EquipDataGrid.SelectedItem;
using (wiki_nolek_dk_dbEntities db = new wiki_nolek_dk_dbEntities())
{
db.Configuration.LazyLoadingEnabled = true;
var equipmentRelation = db.EquipmentComponents.Where(c => c.EquipmentID == selectedEquipment.EquipmentId);
var componentsForEquipment = new List<Component>();
foreach (var row in equipmentRelation)
{
var component = db.Components.FirstOrDefault(c => c.ComponentId == row.ComponentID);
componentsForEquipment.Add(component);
}
CompDataGrid.ItemsSource = componentsForEquipment;
}
}
}
}
catch
{
MessageBox.Show("Det valgte udstyr eksisterer ikke.");
}
}
I have modified your own reply's code to remove useless foreach loop.I don't know how wiki_nolek_dk_dbEntities works exactly, but I'm also adding ToList() to any db query result to make sure the result is a List and not an IQueryable.
private void EquipDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
EquipmentView selectedEquipment = (EquipmentView)EquipDataGrid.SelectedItem;
using (wiki_nolek_dk_dbEntities db = new wiki_nolek_dk_dbEntities())
{
db.Configuration.LazyLoadingEnabled = true;
var equipmentRelationComponentIds =
db.EquipmentComponents
.Where(e => e.EquipmentID == selectedEquipment.EquipmentId)
.Select(e => e.ComponentId)
.ToList();
var componentsForEquipment =
db.Components
.Where(c => equipmentRelationComponentIds.Contains(c.ComponentId))
.ToList();
CompDataGrid.ItemsSource = componentsForEquipment;
}
}
catch
{
MessageBox.Show("Det valgte udstyr eksisterer ikke.");
}
}
I have a OberservableCollection stored in my Isolated Storage.
New a Scene contains a List. And a Light contains an Xpos en Ypos property.
How can I edit this list?
So I would like to retrieve it from the IsoStorage, change the 2 properties and then save it again.
Hope someone can help me out :).
Kind regards,
Niels
ObservableCollection's have a colleciton changed event which passes who sent it (the base collection) as well as a series of arguments. You can listen to this CollectionChanged event, listen to only newly added items and perform your operation on the item.
If your collection is a list of referenced objects, you can perform your edits on the objects directly and the changes will be mirrored in the list. However, if you are using value typed list, then you need a way of flagging the item such that when you remove it from the list, and re-add it, the add doesn't trigger an infinite loop.
Example:
class Clean<T>
{
public T Value;
public bool IsClean;
public Clean(T value, bool clean)
{
Value = value;
IsClean = clean;
}
}
This Clean class is used to store a value as well as a flag marking if its been processed or not.
class Program
{
static void Main(string[] args)
{
ObservableCollection<Clean<int>> myCollection = new ObservableCollection<Clean<int>>();
myCollection.CollectionChanged += x_CollectionChanged;
myCollection.Add(new Clean<int>(2,false));
}
static void x_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
//Grab the collection being modified
ObservableCollection<Clean<int>> collection = sender as ObservableCollection<Clean<int>>;
if (collection == null)
{
// do some error checking action
}
//Only look at items being added
if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
//New item has been added
foreach (Clean<int> newItem in e.NewItems)
{
///Only perform the operation on new "dirty" objects
if (!newItem.IsClean)
{
collection.Remove(newItem);
//Add the new modified value and mark it as clean so that
// this process isn't run again
collection.Add(new Clean<int>(newItem.Value * 2,true));
}
}
}
}
}
Sources:
ObservableCollection MSDN Article
NotifyCollectionChangedEventHandler MSDN Article
I would just retrieve the collection as per normal...
public IEnumerable<Scene> GetScenes()
{
using (var filesystem = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var fs = new IsolatedStorageFileStream("Scenes", FileMode.Open, filesystem))
{
var serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(IEnumerable<Scene>));
return serializer.ReadObject(fs) as IEnumerable<Scene>;
}
}
}
... then edit what you need to...
var myScenes = new ObservableCollection<Scene>(GetScenes());
var itemToUpdate = myScenes.Where(i => i.PropertyToCheck == "value to check");
itemToUpdate.PropertyToSet = "new value";
...and save the collection back to isolated storage using the same key to identify it.
SaveScenes(myScenes);
It will overwrite the previous collection if you use FileMode.Create.
public void SaveScenes(IEnumerable<Scene> scenes)
{
using (var filesystem = IsolatedStorageFile.GetUserStoreForApplication())
{
using (var fs = new IsolatedStorageFileStream("Scenes", FileMode.Create, filesystem))
{
var serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(IEnumerable<Scene>));
serializer.WriteObject(fs, Scenes);
}
}
}
You can find a similar example on MSDN.
I'm trying to learn Entity Framework but i have little problem i can not solve by myself
I'm loading data from MS SQL database to the datagrid and trying to modify/add data from there.
But i don't know how to achieve this.
Here is my code:
using (var context = new OrdersDataModelContainer())
{
var customersQuery = from o in context.Payments
select o;
dataGridView1.DataSource = customersQuery;
}
when i did it this way i get this:
when i modyfy code:
using (var context = new OrdersDataModelContainer())
{
var customersQuery = from o in context.Payments
select o;
dataGridView1.DataSource = customersQuery.ToList();
}
my form looks :
But then i can not modify data or add new rows.
Can anyone help me with this problem by showing some code snippet or pointing where I'll be able to find solution?
Thanks!
#Update
I use VS 2012 and SQL Server 2012 ( if that matters)
This is because the underlying data source of the grid does not support modification. Solution:
using (var context = new OrdersDataModelContainer())
{
var customersQuery = from o in context.Payments
select o;
dataGridView1.DataSource = new BindingList<Payments>(customersQuery.ToList());
}
Thanks to King King's comment
Update:
To save changes you need to preserve the context which actually tracks the modifications on the retrieved entities that are now presented in the grid. So one way (perhaps the simplest way) is to declare context as a form member:
public partial class Form1 : Form
{
private MyDBContext context = new MyDBContext(); // whatever your context name is
private void btnLoadData_Click(object sender, EventArgs e) // when you want to load the data
{
var customersQuery = from o in context.Payments
select o;
dataGridView1.DataSource = new BindingList<Payments>(customersQuery.ToList());
}
private void btnSaveChanges_Click(object sender, EventArgs e) // when you want to save
{
context.SaveChanges();
}
}
Be advised that context is not recommended to be preserved for a long time. There are many articles about life cycle of the context.
I've been using this programming style, that I've seen in an example and just started using it, because it does the job... I would like to know other programmers' opinion about it...
So the situation is when you have a GridView, or a control based on it like the RadGrid, and you want to keep track of a data table while you are adding, editing, reordering and deleting rows.
Using the session to hold the data table (or list of data) may not be the best solution, because the user may open two identical web pages… Using the ViewState to hold the data may be and option... I have been using an approach like the following:
public partial class DefaultPage : System.Web.UI.Page
{
protected DataLine DefaultDataLine()
{
DataLine dl = new DataLine();
dl = new DataLine();
dl.Number = 0;
dl.Title = "";
dl.Text = "";
return dl;
}
protected class DataLine
{
public int Number { get; set; }
public string Title { get; set; }
public string Text { get; set; }
}
protected static List<DataLine> tempLines;
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
tempLines = RadGridBindStartUpData();
}
}
protected void RadGrid1_NeedDataSource(object source, Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
RadGrid1.DataSource = tempLines;
}
protected void RadGrid1_InsertCommand(object source, Telerik.Web.UI.GridCommandEventArgs e)
{
GridEditableItem editedItem = e.Item as GridEditableItem;
List<DataLine> table = tempLines;
DataLine newRow = new DataLine ();
RadTextBox rtb;
rtb = (RadTextBox)editedItem.FindControl("RadTextBoxTitle");
newRow.Title = rtb.Text;
rtb = (RadTextBox)editedItem.FindControl("RadTextBoxDescription");
newRow.Description = rtb.Text;
RadNumericTextBox number = (RadNumericTextBox)editedItem.FindControl("RadNumericTextBoxNumber");
newRow.Number = number.Value.HasValue ? Convert.ToInt32(number.Value.Value) : 0;
table.Add(newRow);
}
// ...
So using a static List variable, of a custom object (class), declared in the code-behind of the Aspx page, and updating it whenever the data is edited.
What are your thoughts about this approach? Is it okay? How do you hold your table-format data for edition (prior to saving it in the database)?
Not exactly sure what you're going for, but using a static variable is probably not what you want to do. Static properties are shared across all user/threads, so all concurrent users would be editing the same data.
If you are just looking to persist a small data set across post-backs to the same page, use the ViewState instead. Just be mindful of potential performance issues if you plan on cramming lots of data into it.
It depends on what you're wanting to achieve
Viewstate will keep the data on that page - it won't be available on any other pages (or tabs, or windows)
Session will keep the data on the server, this means it will be available for any page the user is looking at (on your site) and it will keep it until the session times out.
Theres a lot of advtanges/disadvantages to either method, therefore you need to research your situation, here is a start.
You mentioned storing in the session, and how this could cause issues if the user opens up multiple copies of the page, etc...
We had a similar issue so I made a property in code behind on the page and on first page load (if not postback blah blah) I generate a new guid. Then I use the guid value as my session key and I know it'll be unique per page.
You could make a spify property like this...
Public ReadOnly Property SessionDataKey() As String
Get
If ViewState("SessionDataKey") Is Nothing Then
ViewState("SessionDataKey") = Guid.NewGuid()
End If
Return ViewState("SessionDataKey").ToString()
End Get
End Property
But in short, I just use the session.
Thank you very much for your replies! With your help, and some research, I see that both approaches, storing in session or using the static variable are indeed wrong, at least for the purpose I was using them... All your answers were helpful, and although I can only mark one as correct, I would like to leave my appreciation.
Well, for anyone stumbling across the same problem, here’s what I’ve implemented in my pages:
public partial class ScriptAdd : System.Web.UI.Page
{
private List<MyItem> tempMyItems
{
get
{
//if (ViewState["tempMyItemsList"] == null)
// ViewState["tempMyItemsList"] = new List<MyItem>();
return (List<MyItem>)ViewState["tempMyItemsList"];
}
set
{
ViewState.Add("tempMyItemsList", value);
}
}
protected void Page_Load(object sender, EventArgs e)
{
// ...
}
}
And then use it whenever I want to add / insert / update lines to my temporary list:
List<MyItem> table = tempMyItems;
table.RemoveAt(idx);
MyItem newRow = new MyItem ();
// ...
table.Insert(idx, newRow);
Finally, if intended, I store all the items in the database.