Sorting Table with Foreign Key Columns - c#

I have a Table(Geraete) in the View which also displays data from a Foreign Table by using the public Virtual Key Ort(Foreignkey to Table Orte) to access the other Table. This works fine, but my Problem is when i want to sort the Column of foreign Values the following Code snippet does not work:
//test.Sortcolumn(String Value of the Column name which should be sorted)
var pi = typeof(Geraete).GetProperty("test.SortColumn");
//movie.Typens is from Type List Geraete
movie.Typens = (from t in movie.Typens select t).OrderBy(x => pi.GetValue(x, null)).ToList();
And yes this Snippet works for Columns of the same Entity Type Geraete.
In the View the values of the foreign Tables are easily accessable by using Ort.Columnname but this does also not work with the Code snippet above.

If you want to traverse the navigation property it would be something like
x =>
{
var o = x.GetType().GetProperty("test",x);
var pi o.GetType().GetProperty("SortColumn");
retrun pi.GetValue("SortColumn",o);
}

Related

How to transfer SQL data from one table to another using Entity Framework Core

I have two tables in my database that contain the same columns. TBL one and TBL two which is history table. When I am entering data into TBL 1, I want to move all data from TBL 1 to Tbl 2 (as history data) using EF Core 2.2.
I don't want to write unnecessary loops to make the code ugly.
var MyEntity = new MyEntities();
var TBL1 = MyEntity.TBL1.Find();
var TBL2 = new TBL2();
TBL2.CurrentValues.SetValues(TBL1);
//CurrentValues is not accept in code. Giving me build error
MyEntity.TB2.Add(data2);
MyEntity.TB1.Remove(data1);
MyEntity.SaveChanges();
All I need is copy SQL data from table 1 to table 2 using EF and avoiding loops. Any example with mapper or anything which works will help.
Add a navigation property to your TBL2 model:
public TBL1 TBL1 { get; set; }
Add a projection to your TBL1 model like this:
public static Expression<Func<TBL1, TBL2>> Projection
{
return tbl1 => new TBL2
{
Prop1 = tbl1.Prop1,
Prop2 = tbl1.Prop2,
TBL1 = tbl1,
};
}
And use the projection to have instances of TBL1 and TBL2 like this:
var MyEntity = new MyEntities();
var tbl2 = MyEntity.TBL1.Where(x => x.Id == id).Select(TBL1.Projection).SingleOrDefault();
vat tbl1 = tbl2.TBL1;
MyEntity.TB2.Add(tbl2);
MyEntity.TB1.Remove(tbl1);
MyEntity.SaveChanges();
I assume you don't want to change your table model just for copying data, you want to copy from one table to another, possibly to a different database.
So you could try it with something like this. Use ClearTable to make the target table empty, then copy the items:
void ClearTable<T>(System.Data.Linq.Table<T> tbl, bool submitChanges = true)
where T : class
{
tbl.DeleteAllOnSubmit(tbl);
if (submitChanges) ctxSrc.SubmitChanges();
}
void CopyTable<T>(System.Data.Linq.Table<T> srcTbl,
System.Data.Linq.Table<T> tgtTbl, bool submitChanges = true)
where T : class
{
ClearTable(tgtTbl, submitChanges);
foreach (var element in srcTbl.Select(s => s).ToList())
{
tgtTbl.Append(element);
}
if (submitChanges) ctxTgt.SubmitChanges();
}
Example 1: Copy from one table to another (same database)
CopyTable(ctxSrc.Products1, ctxSrc.Products2);
Example 2: Copy from one database to another
CopyTable(ctxSrc.Products, ctxTgt.Products);
This assumes that you have two database contexts: ctxSrc and ctxTgt and you want to copy from the source context to the target context.
Notes:
The code above deletes items from the target table before copying. Comment the ClearTable call if you just want to append data.
The example doesn't regard dependencies such as foreign key relationshios. You have to add that to the code if required. For example, copying tables in the right order is important. If you have a foreign key pointing to another table you have to copy that table first. Similar rules apply to deletion of rows which contain foreign keys.
If you have many elements, consider to submit more often. This example will hold all elements in memory before it submits. You could achieve this through paging. You can append .Skip(n) and .Take(m) methods for this purpose.
Other than SQL does Entity Framework (Core) not know any true bulk operations. Even tbl.DeleteAllOnSubmit(tbl), which looks like one (it is an integrated method), does internally loop through all elements in order to remove them.

LINQ DeleteOnSubmit without Primary key

I have the following code and I want to delete all rows from TABLE where the column 'id' IS NOT Primary Key.
#{
using (var db = new DataClassesDataContext())
{
var query = db.Table.Where(r => r.id == 2).ToList();
if (query != null)
{
foreach (var q in query)
{
db.Table.DeleteOnSubmit(q);
}
}
db.SubmitChanges();
}}
This throws a System.InvalidOperationException because the table has not Primary Key column.
How is it possible to do that without adding a primary key in the SQL Server database?
Thanks in advance
Open the LINQ Designer. Open the properties window for the table you want to delete a record from. Click on any of the columns in the entity you want to delete and you'll see a property labeled "Primary Key". Change the value to true for column you want to use as a primary key.
P/S:This will not set the primary key on your real table.

Telerik grid foreign key

I have two tables, one is tblKunde and the other is tblHistorie.
They look like this:
TblKunde:
You can see the KdNr is the primary key of it.
TblHistorie:
You can see that Id is the primary key and KdNr is a foreign key which points to to the KdNr of table tblKunde.
Now my goal is to display the table TblHistorie as a KendoUI grid with columns Datum, Aktion and instead of a column KdNr it should display the Name of tblKund.
So basically it is very simple. The grid should not display the KdNr cell instad the Name of the foreignkey table.
This is a snippet of my table which are displaying columns Datum and Aktion:
.Columns(columns =>
{
columns.Bound(c => c.Id).Hidden();
columns.Bound(c => c.KdNr); // this should be the Name
columns.Bound(c => c.Datum);
columns.Bound(c => c.Aktion);
})
This is just a snippet and I marked where the name should be displayed instead of KdNr. Can someone say me how to do this?
Here is the solution for displaying values of s foreign table which is hooked up by a foreign key:
These are the tables to illustrate it better:
KdNr is the foreign key in this case
In our grid we want to display the Name from tblKunde
Our grid is bound to tblHistorie so we have to use a foreign key do display the name of tblKunde
Firstly you need to query through the foreign table like this. This is done inside the controller:
public ActionResult ToDo()
{
// Connection to database table
KundeContext KundenContext = new KundeContext();
// Select all properties from table. Especially the foreign key!!
ViewData["Kunde"] = KundenContext.Kundes.Select(e => new { KdNr = e.KdNr, Name = e.Name, Vorname = e.Vorname, Berater = e.Berater }).ToList();
return View();
}
You have to select all properties you want form the foreign table as well as the foreign key. In my case this is KdNr.
Now that you have selected all properties, put it inside your ViewBag or ViewData so that you can use it later inside the view.
Inside the grid:
columns.ForeignKey(p => p.KdNr, (System.Collections.IEnumerable)ViewData["Kunde"], "KdNr", "Name").Title("Name");
Bind to the foreign key as you would to a normal column (p => p.KdNr). It is important that you do this via columns.ForeignKey. The next step is to use IEnumerable to query through your list and bind it to your ViewData. Behind it put your foreign key in quotes (KdNr in my case) and then the column of the foreign table which you want it to bind (Name in my case). This has to be in the ViewData from the first step!!

Get present primary keys from link table, set Checkstate checklistbox

I have a CheckedListbox which contains values from some table called products.
The idea is to check the products that are associated to a customer. Now it does save correctly in an link table, yet when loading it again, the items that were checked do not get loaded correctly into the CheckedListbox.
So from that link table where, I would like to get all rows from just one column. All tables are already loaded into the application so I don't want to use sql.
I've tried using linq, with no success, Ids is just empty here.
int[] Ids = (from m in dataset.Tables["LinkTable"].AsEnumerable()
where m.Field<int>("customerId") == customerId
select m.Field<int>("productId")).ToArray();
Then, if I do succeed to get those Id's, I would like to get the indexes of those primary keys so I can set the correct products to checked.
I've tired doing it like this, but this gives me error in other parts of the program, because I am setting a Primary key to a global datatable. Datagridviews don't like that.
DataColumn[] keyColumns = new DataColumn[1];
keyColumns[0] = dataset.Tables["products"].Columns["Id"];
currentPatient.GetTheDataSet.Tables["products"].PrimaryKey = keyColumns;
foreach (int Id in Ids)
{
DataRow row = dataset.Tables["Products"].Rows.Find(Id);
int index = dataset.Tables["Products"].Rows.IndexOf(row);
clbMedications.SetItemChecked(index, true);
}
I would like to do that last part without specifying a primary key, I couldn't find how to do that in linq.
I know it consists of 2 questions, but perhaps this can be done with just one linq statement so I better combine them.
[EDIT]
Finally, i think i've got what you need:
var qry = (from p in ds.Tables["products"].AsEnumerable()
select new {
Id = p.Field<int>("Id"),
Index = ds.Tables["products"].Rows.IndexOf(p),
Checked = ds.Tables["LinkTable"].AsEnumerable().Any(x=>x.Field<int>("productId") == p.Field<int>("Id") && x.Field<int>("customerId")==customerid)
}).ToList();
Above query returns the list, which you can bnid with CheckedListbox.

Entity Framework Update existing foreign Key reference to another

I have two tables Team_DATA and Driver_PROFILE_DATA in an SQL database. For every driver_profile there can be many teams.
So there's a one-to-many relation on the driver_profile to team_data table. I want to update a team_data foreign key reference in the Driver_profile table of an already existing record to another team_data record that already exists.
I want to do this using entity framework. Here what I want: having a list of teams to select from, finding the record in the team_data table and updating it's FK in the driver_profile appropriately.
So in the code below, the passed parameter is the newly selected team out of the team_data table.
Now I need it to update it FK reference in the Driver_profile table.
Here's what I've got:
UPDATE: Code Updated. It does not save it to database, even if I call savechanges. No errors.
public Driver_PROFILE_DATA GetSelectedTeam(string team)
{
ObjectQuery<Team_DATA> td = raceCtxt.Team_DATA;
ObjectQuery<Driver_PROFILE_DATA> drpr = raceCtxt.Driver_PROFILE_DATA;
var selteam = from t in td where t.Team_Name == team select t;
Team_DATA newteam = new Team_DATA();
newteam = selteam.Select(x => x).First();
// get driver_profile with associated team_data
var data = from a in raceCtxt.Driver_PROFILE_DATA.Include("Team_DATA") select a;
// put it in driver_profile entity
profileData = data.Select(x => x).First();
profileData.Team_DATAReference.Attach(newteam);
return profileData;
}
Entity Framework should give you a nice Association between the two classes, Update the references as you would using POCOs and stay away from the ID values.
Something like:
newTeam.Profile.Teams.Remove(profileData); // separate from old Profile
profileData.Teams.Add(newTeam);
EDIT:
I made a little test, it is sufficient to set the reference to the Parent object:
newTeam.Profile = profileData;

Categories