WCF RIA -joining two tables - silverlight

I found a lot of explanations about this issue, but nothing that really helped me. The thing is simple. I have two tables on my dataModel: Events and TimeStamps, both have the field EntryID, which is the relation between them(the tables are in fact Views, I can't perform changes on DB, I can only query them).On my domainService, I have the created methods for getting data from each of the tables. So far, I am able to fill a dataGrid with data from only one of the tables, but what I really need is to display from both tables. In T-SQL it would be something like:
Select e.EntryID,t.closed_time
from Events e inner join TimeStamps t
on e.EntryID=t.EntryID
So I want to display on my dataGrid the Entry_ID and closed_time.I appreciate your help for solving my problem
I tried a new custom class
public class CustomTable
{
public string EntryId { get; set; }
public int closed_time { get; set; }
}
public IQueryable<CustomTable> GetJoined()
{
return (from i in this.ObjectContext.Events
join p in this.ObjectContext.TimeStamps p
on i.Entry_ID equals p.Entry_ID
select new CustomTable
{
EntryId = i.Entry_ID,
closed_Time = p.Closed_TIME
});
}
This is the additional code I added by myself, I'm pretty sure something is missing, this method and the class itself were added on my service.cs

This is the final code and procedures done, do not forget to build the project after each step:
1- Opened a new class under Myproject.Web(Add-->new item-->class)
namespace Myproject.Web
{
public class CustomTable
{
[Key]
public string EntryId { get; set; }
public int closed_Time { get; set; }
}
}
2-Added on IncidentService.cs:
public IQueryable<CustomTable> GetJoined()
{
return (from i in this.ObjectContext.Events
join p in this.ObjectContext.TimeStamps p
on i.Entry_ID equals p.Entry_ID
select new CustomTable
{
EntryId = i.Entry_ID,
closed_Time = p.Closed_TIME
});
}
3-Added on Mypage.xaml.cs
public MyPage()
{
InitializeComponent();
this.dataGrid1.ItemsSource = _IncidentContext.CustomTables;
_IncidentContext.Load(_IncidentContext.GetJoinedQuery());
DataGridTextColumn entry = new DataGridTextColumn();
entry.Binding = new System.Windows.Data.Binding("EntryId");
entry.Header = "Entry Id";
DataGridTextColumn closed = new DataGridTextColumn();
closed.Binding = new System.Windows.Data.Binding("closed_Time");
closed.Header = "Closed Time";
dataGrid1.Columns.Add(entry);
dataGrid1.Columns.Add(closed);
}
I hope this will help others with same issue, I spent 3 days working on this solution!!

Related

Winforms, EF Core, dropdown combobox bound to BindingSource. Is there a descent way of persisting newly added items? BindingList?

I am trying to build a Patient's edit form that will get Patient data from a database using EF Core and the DbContext derived AppDbContext.
On the same form there will be a dropdown combobox that will be displaying all the available insurances (fetched from the database).
What I want to achieve is the ability, the user to be able to select an existing insurance (which is obvious and easily achieved) or to add a new one by typing it into the combobox and this new entry should be selected as the patient's insurance from now on until the SaveChanges takes place and when the same patient is reopened for editing.
I use two BindingSources one for the patient itself (bsPatient) and one for the insurances list (bsInsurances).
I have the following two models (1:many relationship)
public class Insurance
{
public int Id { get; set; }
public string Name { get; set; } = String.Empty;
public virtual ObservableCollectionListSource<Person> Persons { get; } = new();
}
public class Person
{
public int Id { get; set; }
public string LastName { get; set; } = String.Empty;
public string FirstName { get; set; } = String.Empty;
public DateTime DOB { get; set; }
public int InsuranceId { get; set; }
public Insurance Insurance { get; set; } = null;
}
And this is the DbContext:
public class AppDbContext : DbContext
{
private const string DatabaseFileName = "MyPatientsDB.sqlite3";
public DbSet<Person> Persons { get; set; }
public DbSet<Insurance> Insurances { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder
.UseSqlite(#$"Data Source={DatabaseFileName}");
On the form there will be
public partial class PatientForm : Form
{
private AppDbContext _db = new();
private int _patientId = 0;
ObservableCollection<Insurance> _insurancesList = new();
public PatientForm(int patientId)
{
InitializeComponent();
_patientId = patientId;
}
protected async override void OnLoad(EventArgs e)
{
base.OnLoad(e);
await _db.Insurances.LoadAsync();
_insurancesList = new ObservableCollection<Insurance>(_db.Insurances.Local);
bsInsurances.DataSource = _insurancesList;
bsPatient.DataSource = await _db.Persons.FirstOrDefaultAsync(p => p.Id == _patientId);
}
protected async override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
bsInsurances.EndEdit();
if (cbInsurances.FindStringExact(cbInsurances.Text) == -1)
{
var newInsurance = new Insurance { Id = 0, Name = cbInsurances.Text };
_db.Insurances.Local.Add(newInsurance);
}
bsPatient.EndEdit();
await _db.SaveChangesAsync();
_db?.Dispose();
}
}
So far, I am able to save correctly the Insurance selection of the combobox when an already existing item is selected. The problem arises when the user inserts a new insurance entry into the combo textbox. This new entry can not be saved to the db and be displayed the next time the same patient is opened for editing.
I would be grateful if someone could point me towards which direction to follow to achieve this. I mean, while editing a patient's data how to be able to insert a new entry into the insurances combo and this new entry to be persisted into the db and be displayed and selected the next time the patient is opened for editing.
I think I've found a solution. I don't know if it is the best one but it seems to be working at least into my project. I am just referring it in case someone else has the same query.
Please if anyone has a better solution I would be grateful for his/her help.
protected async override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
bsInsurances.EndEdit();
if (cbInsurances.FindStringExact(cbInsurances.Text) == -1)
{
if (bsPatient != null && bsPatient.DataSource != null)
{
(bsPatient.DataSource as Person).Insurance = new Insurance() { Name = cbInsurances.Text as string };
}
}
bsPatient.EndEdit();
await _db.SaveChangesAsync();
_db?.Dispose();
}

Multi Mapping in Dapper. Receiving the error in SpiltOn

*Can You explain the Split on function in the multimap *
I am Trying to get the data from the Database using Dapper ORM. I have received the following error
System.ArgumentException : When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id
Parameter name: splitOn
public abstract class Domain
{
public Guid Id { get; set; }
}
public abstract class ItemBase : Domain
{
private IList<Image> images = new List<Image>();
public Guid? ParentId { get; set; }
public string Name { get; set; }
public IList<Image> Images { get { return images; } }
}
public class Meal : ItemBase
{
}
public class Item : ItemBase
{
private IList<Meal> meals = new List<Meal>();
public IList<Meal> Meals { get { return meals; } };
}
public class Image : Domain
{
public byte Img { get; set; }
public string Description { get; set; }
}
public class MealImageLink : Domain
{
public Guid ItemId { get; set; }
public Guid ImageId { get; set; }
}
/* search function to take dat from the table */
private List<Meal> SearchMeals(Guid id)
{
var query = #"SELECT meal.[Name],meal.[Description],meal.
[Price],mealImage.[Image] as Img
FROM [MealItems] as meal
LEFT JOIN [MealImageLink] mealImageLink
on meal.Id= mealImageLink.MealItemId
LEFT JOIN [Images] mealImage on
mealImageLink.ImageId=mealImage.Id
WHERE meal.[ParentId]=#Id";
List<Meal> meals = ( _connection.Query<Meal, MealImageLink, Image, Meal>
(query, (meal, mealLink, mealImage) =>
{
meal.Images.Add(mealImage);
return meal;
}, new { #Id = id })).ToList();
return meals;
}
The multi-map feature is really more intended for scenarios like:
select foo.Id, foo.whatever, ...,
bar.Id, bar.something, ...,
blap.Id, blap.yada, ...
from foo ...
inner join bar ...
left outer join blap ...
or the lazier but not uncommon:
select foo.*, bar.*, blap.*
from ...
inner join bar ...
left outer join blap ...
But in both of these cases, there is a clear and obvious way to split the horizontal range into partitions; basically, whenever you see a column called Id, it is the next block. The name Id is configurable for convenience, and can be a delimited list of columns for scenarios where each table has a different primary key name (so User might have UserId, etc).
Your scenario seems quite different to this. It looks like you're currently only selecting 4 columns with no particular way of splitting them apart. I would suggest that in this case, it is easier to populate your model via a different API - in particular, the dynamic API:
var meals = new List<Meal>();
foreach(var row in _connection.Query(sql, new { #Id = id }))
{
string name = row.Name, description = row.Description;
decimal price = row.Price;
// etc
Meal meal = // TODO: build a new Meal object from those pieces
meals.Add(meal);
}
The dynamic API is accessed simply by not specifying any <...>. With that done, columns are accessed by name, with their types implied by what they are being assigned to - hence things like:
decimal price = row.Price;
Note: if you want to consume the row data "inline", then just cast as soon as possible, i.e.
// bad: forces everything to use dynamic for too long
new Meal(row.Name, row.Description, row.Price);
// good: types are nailed down immediately
new Meal((string)row.Name, (string)row.Description, (decimal)row.Price);
Does that help?
Tl;dr: I just don't think multi-mapping is relevant to your query.
Edit: here's my best guess at what you intend to do - it simply isn't a good fit for multi-map:
var meals = new List<Meal>();
foreach (var row in _connection.Query(query, new { #Id = id })) {
meals.Add(new Meal {
Name = (string)row.Name,
Images = {
new Image {
Description = (string)row.Description,
Img = (byte)row.Img
}
}
});
}
return meals;

Dapper - What is the most efficient way to query Many-To-Many relationship?

I am new to Dapper and trying to figure out how to query a Many-To-Many relationship.
I've looked around SO and Google but could not find an example.
I have a simple Many-To-Many scenario with 3 tables:
Albums table:
Artists table:
and the Many-To-Many table:
These are my POCOS:
public class Artist
{
public long Id { get; set; }
public string Name { get; set; }
}
public class Album
{
public long Id { get; set; }
public string Name { get; set; }
public List<Artist> Artists { get; set; }
}
Can someone provide the "correct" and efficient way to get a list of albums, and each album contains it's artists (the artists should have their Name property filled also) ?
I'm sure you must have found the solution by now. This could be helpful, may not be the neatest way to code it.
Is it possible to replicate Album and Artist classes?
If so, this is what i would do.
public List<Artist> GetAll()
{
using (SqlConnection conn = new SqlConnection(Conn.String))
{
conn.Open();
using (var multi = conn.QueryMultiple(StoredProcs.Artists.GetAll, commandType: CommandType.StoredProcedure))
{
var artists = multi.Read<Artist, AlbumArtist, Artist>((artist, albumArtist) =>
{
artist.albumArtist = albumArtist;
return artist;
}).ToList();
var albums = multi.Read<Album, AlbumArtist, Album>(
(album, albumArtist, album) =>
{
album.albumArtist = album;
return albums;
}).ToList();
conn.Close();
return artists;
}
}
}
Here's how the proc would look like
CREATE PROCEDURE [dbo].[YourProcName]
AS
BEGIN
SET NOCOUNT ON;
SELECT * from Artist a
left join AlbumArtist aa
on a.ArtistId = aa.ArtistId;
EXEC dbo.Album_GetAll
WITH RESULT SETS UNDEFINED;
END
Hope this helps.

hiearchical data, catel, and MVVM

I'm working with Catel, MVVM, WPF and am wondering about how to work with nested/hiearchical data.
Let's say from a database I've got a list of Customers, each with a list of Invoices, each with a list of InvoiceItems. Customers own many Invoices which own many InvoiceItems.
I've got a working solution, but I do not like it. My approach was to build a collection of classes that would act a kind of like an ado.net “dataset.” A class would represent each layer of the hiearchy.
This top level class, CustomerModel, would contain a collection of of InvoiceBlocks:
CustomerModel
ObservableCollection of < InvoicesBlocks >
Each InvoceBlock would contain an Invoice and a collection of InvoiceItems:
InvoiceBlock
Invoice
ObservableCollection of < InvoiceItems >
It seemed clever until wading through the databinding path= satements. There are also times when I have to loop through the sets mamaully to update totals, defeating a major selling point of MVVM.
So, I've decided to learn more about grouping with LINQ queries and databinding. Is this the way the pros do it?
What you can do is make each view model responsible for using the right services to retrieve the data.
Note that I did not use Catel properties to make it easy to understand, but you can simply use Catel.Fody or rewrite the properties to get Catel properties.
public class CustomerViewModel
{
private readonly IInvoiceService _invoiceService;
public CustomerViewModel(ICustomer customer, IInvoiceService invoiceService)
{
Argument.IsNotNull(() => customer);
Argument.IsNotNull(() => invoiceService);
Customer = customer;
_invoiceService = invoiceService;
}
public ICustomer Customer { get; private set; }
public ObservableCollection<IInvoice> Invoices { get; private set; }
protected override void Initialize()
{
var customerInvoices = _invoiceService.GetInvoicesForCustomer(Customer.Id);
Invoices = new ObservableCollection<IInvoice>(customerInvoices);
}
}
public class InvoiceViewModel
{
private readonly IInvoiceService _invoiceService;
public InvoiceViewModel(IIinvoice invoice, IInvoiceService invoiceService)
{
Argument.IsNotNull(() => invoice);
Argument.IsNotNull(() => invoiceService);
Invoice = invoice;
_invoiceService = invoiceService;
}
public IInvoice Invoice { get; private set; }
public ObservableCollection<IInvoiceBlock> InvoiceBlocks { get; private set; }
protected override void Initialize()
{
var invoiceBlocks = _invoiceService.GetInvoiceBlocksForInvoice(Invoice.Id);
InvoiceBlocks = new ObservableCollection<IInvoiceBlock>(invoiceBlocks);
}
}
Now you are fully in control what happens when.

Entity framework not updating self-referenced key

I've got my entity class (which is part of my Entity Framework Code First DbContext) like this:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Person Boss { get; set; }
public decimal Piotrus { get; set; }
}
Now I'm trying to update persons boss like this:
using(var db = new DataContext())
{
var employee = db.Persons.Single(p => p.Name = "Kowalski");
employee.Boss = db.Persons.Single(p => p.Name = "Malysz");
db.Entry(employee).State = State.Modified;
db.SaveChanges();
}
While debugging entity seems to be ok. It have right Boss assigned. Even when I tried to get data from current DbContext it looks fine, but in Database property Boss_Id stays still unchanged, while other properties (if were changed) has been modified.
Also everything works okay when I'm creating a person. Assigned boss is stored correctly.
What can cause this problem?
Try commenting out db.Entry(employee).State = State.Modified;

Resources