Silverlight 5 validation issue - validation

i'm trying to validate the data entry of my project using the validation in silverlight
this is the result
http://imageshack.us/photo/my-images/842/immagineleb.png/
as you can see the borders of almost all the textboxes are red, actually, in this case, no one of them should be red! And in all of the tooltips there's the same message.
there are the properties of the object that i use in the data context of the form
private int matricola;
public int Matricola
{
get { return matricola; }
set
{
ValidateRequiredInt("Matricola", value, "Inserire un numero");
matricola = value;
OnNotifyPropertyChanged("Matricola");
}
}
private String cognome;
public String Cognome
{
get { return cognome; }
set
{
ValidateRequiredString("Cognome", value, "Inserire cognome");
cognome = value;
OnNotifyPropertyChanged("Cognome");
}
}
private String nome;
public String Nome
{
get { return nome; }
set
{
ValidateRequiredString("Nome", value, "Inserire nome");
nome = value;
OnNotifyPropertyChanged("Nome");
}
}
private String codiceUtente;
public String CodiceUtente
{
get { return codiceUtente; }
set
{
ValidateRequiredString("CodiceUtente", value, "Inserire codice utente");
codiceUtente = value;
OnNotifyPropertyChanged("CodiceUtente");
}
}
private String password;
public String Password
{
get { return password; }
set
{
ValidateRequiredString("Password", value, "Inserire password");
password = value;
OnNotifyPropertyChanged("Password");
}
}
private int? idOrario;
public int? IdOrario
{
get { return idOrario; }
set { idOrario = value; }
}
private DateTime? dataAssunzione;
public DateTime? DataAssunzione
{
get { return dataAssunzione; }
set
{
if (value != null)
{
ValidateDateTime("DataAssunzione", (DateTime)value, "Immettere una data corretta");
if (((DateTime)value).Year == 1 && ((DateTime)value).Month == 1 && ((DateTime)value).Day == 1)
{
dataAssunzione = null;
}
else
{
dataAssunzione = value;
}
OnNotifyPropertyChanged("DataAssunzione");
}
else
{
dataAssunzione = null;
}
}
}
private DateTime? dataLicenziamento;
public DateTime? DataLicenziamento
{
get { return dataLicenziamento; }
set
{
if (value != null)
{
ValidateDateTime("DataLicenziamento", (DateTime)value, "Immettere una data corretta");
if (((DateTime)value).Year == 1 && ((DateTime)value).Month == 1 && ((DateTime)value).Day == 1)
{
dataLicenziamento = null;
}
else
{
dataLicenziamento = value;
}
OnNotifyPropertyChanged("DataLicenziamento");
}
else
{
dataLicenziamento = null;
}
}
}
private int idGruppoAnag;
public int IdGruppoAnag
{
get { return idGruppoAnag; }
set { idGruppoAnag = value; }
}
private int? costoOrario;
public int? CostoOrario
{
get { return costoOrario; }
set
{
if (value != null)
{
ValidateInt("CostoOrario", (int)value, "Immettere un numero o lasciare il campo vuoto");
if (value == 0 || value == -1)
{
costoOrario = null;
}
else
{
costoOrario = value;
}
OnNotifyPropertyChanged("CostoOrario");
}
else
{
costoOrario = null;
}
}
}
and these are the methods used for the validation
protected bool ValidateRequiredInt(string propName, int value, string errorText)
{
if (DataErrors.ContainsKey(propName))
{
DataErrors[propName].Remove(errorText);
}
if (value == 0 || value == -1)
{
AddError(propName, errorText);
return false;
}
OnErrorsChanged(propName);
return true;
}
//validazione dei campi che richiedono numeri interi nullable
protected bool ValidateInt(string propName, int value, string errorText)
{
if (DataErrors.ContainsKey(propName))
{
DataErrors[propName].Remove(errorText);
}
if (value == 0)
{
AddError(propName, errorText);
return false;
}
OnErrorsChanged(propName);
return true;
}
//validazione dei campi che richiedono stringhe
protected bool ValidateRequiredString(string propName, string value, string errorText)
{
//Clear any existing errors since we're revalidating now
if (DataErrors.ContainsKey(propName))
{
DataErrors[propName].Remove(errorText);
}
if (string.IsNullOrEmpty(value))
{
AddError(propName, errorText);
return false;
}
OnErrorsChanged(propName);
return true;
}
protected bool ValidateDateTime(string propName, DateTime value, string errorText)
{
//Clear any existing errors since we're revalidating now
if (DataErrors.ContainsKey(propName))
{
DataErrors[propName].Remove(errorText);
}
if (value.Year == 9999 && value.Month == 12 && value.Day == 31)
{
AddError(propName, errorText);
return false;
}
OnErrorsChanged(propName);
return true;
}
i'm also using using a dataconverter, in the two "Data" textboxes, and numberconverter, in the matricola and costo textboxes, as locals resources and i can say that they work fine.
i'm missing something?

How about implementing INotifyDataErrorInfo?
In a view-model base class:
public abstract class BaseViewModel : INotifyPropertyChanged, INotifyDataErrorInfo
{
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
#region INotifyDataErrorInfo Members
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public System.Collections.IEnumerable GetErrors(string propertyName)
{
....
}
public System.Collections.IEnumerable GetErrors()
{
...
}
//Plus methods to push errors into an underlying error dictionary used by the above error get methods
}
Expand on this and you will have reusable base class for all view-models.
Validate properties in the appropriate setters. If they fail validation then push an error into the error dictionary keyed by property name. If validation succeeds then remove the validation error (if any) from the the dictionary for the property.
You will need to fire the ErrorsChanged event when you change the dictionary, but this can be achieved by having a protected
SetErrorForProperty(string propName, object error)
method whcih wraps this up.
Clearing an error can be done by passing null to this method and/or by having a separate
ClearErrorsFroProperty(string propName)
method.

Related

how to show a alert if table is empty?

I want to show a alert if table is empty, problem is that i have to click twice before he is hitting
the else statement to show my alert.
I use a overlay to show the devices.
I tried OnafterrenderAsync, OnInitializedAsync, OnParameterSetAsync
If the api call gets devices than there is no problem, the table is loading but if there is no data in the table he doesn't go to the else statement to show my mudalert
<PageTitle>#AccountResource.DevicesLinkLabel</PageTitle>
#if (isLoading)
{
}
else
{
#if (!isShowing)
{
<MudTable T="DeviceModel" ServerData="#(new Func<TableState, Task<TableData<DeviceModel>>>(LoadData))" Hover="true" Breakpoint="Breakpoint.Sm" Dense="true" #ref="table">
<HeaderContent>
<MudTh>#AccountResource.DevicesLinkLabel</MudTh>
<MudTh>#SharedResource.Type</MudTh>
<MudTh>#SharedResource.Version</MudTh>
<MudTh>#SharedResource.VersionAppNumber</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="DeviceName">#context.DisplayName</MudTd>
<MudTd DataLabel="DeviceType">#context.Type</MudTd>
<MudTd DataLabel="DeviceVersion">#context.Version</MudTd>
<MudTd DataLabel="DeviceVersionAppNumber">#context.VersionAppNumber</MudTd>
</RowTemplate>
<PagerContent>
<MudTablePager />
</PagerContent>
</MudTable>
}
else
{
<MudAlert Severity="MudBlazor.Severity.Warning">#SharedResource.NothingToShow</MudAlert>
}
}
#code {
[Parameter]
public long UserId { get; set; }
[Parameter]
public long OrganisationId { get; set; }
[Parameter]
public EventCallback<ModelBase> ShowResponseInToast { get; set; }
private MudTable<DeviceModel>? table;
private bool isLoading = true;
private bool isShowing;
protected override async Task OnParametersSetAsync()
{
try
{
if (table != null)
{
//table.CurrentPage = 0;s
await table.ReloadServerData();
}
}
finally
{
isLoading = false;
}
}
private async Task<TableData<DeviceModel>> LoadData(TableState state)
{
var request = new GetDeviceRequest
{
OrganisationId = OrganisationId,
UserId = UserId,
Page = state.Page,
PageSize = state.PageSize,
};
var response = await DeviceManagerClient.GetDeviceResponseAsync(request);
if (table?.Items?.Any() == true)
{
isShowing = false;
return new TableData<DeviceModel>
{
Items = response.Results,
TotalItems = response.TotalCount
};
}
else
{
isShowing = true;
return new TableData<DeviceModel>
{
Items = response.Results,
};
}
}
}

Issue with Xamarin Firebase Subscribe to a Child with no Key - Newtonsoft.Json error

I have a Firebase Child called "Parameters" that stores some data while my program runs. I populate it with "Put" and "Patch" actions. I cannot get the subscribe to work... I'm stuck on this Newtonsoft.Json.JsonSerializationException and I've tried several things but cannot figure it out. You can see in the error, I am getting the payload back... I just cannot parse it into my ViewParameterModel property variables. I would appreciate any help to get this working. Thanks, Brian
$exception {Firebase.Database.FirebaseException: Exception occured while processing the request.
Request Data: Response: {"aug":true,"fan":true,"ign":false,"mode":"Off","target":200}
---> Newtonsoft.Json.JsonSerializationException: Error converting value True to type 'Chart_sample.ViewParameterModel'. Path 'aug', line 1, position 11.
---> System.ArgumentException: Could not cast or convert from System.Boolean to Chart_sample.ViewParameterModel.
FirebaseHelper.cs
...
private readonly string ChildParams = "ControllerData/Pellet_Pirate_1/Parameters";
public ObservableCollection<Parameter> GetParameters()
{
firebase.Child(ChildParams).AsObservable<ViewParameterModel>().Subscribe(snapp =>
{
ViewParameterModel.aug = snapp.Object.aug;
ViewParameterModel.fan = snapp.Object.fan;
ViewParameterModel.ign = snapp.Object.ign;
ViewParameterModel.mode = snapp.Object.mode;
ViewParameterModel.target = snapp.Object.target;
});
return null;
}
...
ViewParameterModel.cs
public class ViewParameterModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool Fan = false;
public bool fan
{
get
{
return Fan;
}
set
{
if (Fan != value)
{
Fan = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("fan"));
}
}
}
private bool Igniter = false;
public bool ign
{
get
{
return Igniter;
}
set
{
if (Igniter != value)
{
Igniter = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ign"));
}
}
}
private bool Auger = false;
public bool aug
{
get
{
return Auger;
}
set
{
if (Auger != value)
{
Auger = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("aug"));
}
}
}
private string Mode = "Off";
public string mode
{
get
{
return Mode;
}
set
{
if (Mode != value)
{
Mode = value;
Debug.WriteLine("Mode: " + Mode);
if (SegmentBindingContext != null)
{
SegmentBindingContext.index = Mode.Equals("Off") ? 0 : Mode.Equals("Start") ? 1 : Mode.Equals("Smoke") ? 2 :
Mode.Equals("Hold") ? 3 : Mode.Equals("Ignite") ? 4 : 5;
}
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("mode"));
}
}
}
private int Target = 0;
public int target
{
get
{
return Target;
}
set
{
if (Target != value)
{
Target = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("target"));
}
}
}
}
}

how to implement Android In App BillingClient in Xamarin.Android Asynchronously

I am trying to implement below java code in c# referring to Android documentation
List<String> skuList = new ArrayList<> ();
skuList.add("premium_upgrade");
skuList.add("gas");
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(SkuType.INAPP);
billingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
#Override
public void onSkuDetailsResponse(BillingResult billingResult,
List<SkuDetails> skuDetailsList) {
// Process the result.
}
});
I have here 2 questions. I thought that i would run this code on a separate thread than UI thread like below to keep my ui responsive while network connection is done. is that the correct approach? QuerySkuDetailsAsync is called async but doesnt implement as async. how should this be working and how to handle in c# because it will fire and forget but Listener to handle the response.
public async Task<List<InAppBillingProduct>> GetProductsAsync(List<string> ProductIds)
{
var getSkuDetailsTask = Task.Factory.StartNew(() =>
{
var prms = SkuDetailsParams.NewBuilder();
var type = BillingClient.SkuType.Inapp;
prms.SetSkusList(ProductIds).SetType(type);
BillingClient.QuerySkuDetailsAsync(prms.Build(), new SkuDetailsResponseListener());
return InAppBillingProducts;
});
return await getSkuDetailsTask;
}
2nd question regarding how to handle with the listener as below. How do I return value from the listener. I need return list of InAppBillingProduct object.
public class SkuDetailsResponseListener : Java.Lang.Object, ISkuDetailsResponseListener
{
public void OnSkuDetailsResponse(BillingResult billingResult, IList<SkuDetails> skus)
{
if (billingResult.ResponseCode == BillingResponseCode.Ok)
{
// get list of Products here and return
}
}
}
FYI. This is how I did it. This is not a complete code but this will give you and idea.
Listener - PCL
============
private async Task EventClicked()
{
var skuList = new List<string>();
skuList.Add("[nameofsubscriptionfoundinyourgoogleplay]");
if (await _billingClientLifecycle.Initialize(skuList, DisconnectedConnection))
{
var firstProduct = _billingClientLifecycle?.ProductsInStore?.FirstOrDefault();
if (firstProduct != null)
{
//purchase here
}
}
}
private void DisconnectedConnection()
{
//Todo.alfon. handle disconnection here...
}
Interface - PCL
===========
public interface IInAppBillingMigratedNew
{
List<InAppBillingPurchase> PurchasedProducts { get; set; }
List<InAppBillingProduct> ProductsInStore { get; set; }
Task<bool> Initialize(List<String> skuList, Action onDisconnected = null);
}
Dependency - Platform Droid
===============
[assembly: XF.Dependency(typeof(InAppBillingMigratedNew))]
public class InAppBillingMigratedNew : Java.Lang.Object, IBillingClientStateListener
, ISkuDetailsResponseListener, IInAppBillingMigratedNew
{
private Activity Context => CrossCurrentActivity.Current.Activity
?? throw new NullReferenceException("Current Context/Activity is null");
private BillingClient _billingClient;
private List<string> _skuList = new List<string>();
private TaskCompletionSource<bool> _tcsInitialized;
private Action _disconnectedAction;
private Dictionary<string, SkuDetails> _skusWithSkuDetails = new Dictionary<string, SkuDetails>();
public List<InAppBillingPurchase> PurchasedProducts { get; set; }
public List<InAppBillingProduct> ProductsInStore { get; set; }
public IntPtr Handle => throw new NotImplementedException();
public Task<bool> Initialize(List<string> skuList, Action disconnectedAction = null)
{
_disconnectedAction = disconnectedAction;
_tcsInitialized = new TaskCompletionSource<bool>();
var taskInit = _tcsInitialized.Task;
_skuList = skuList;
_billingClient = BillingClient.NewBuilder(Context)
.SetListener(this)
.EnablePendingPurchases()
.Build();
if (!_billingClient.IsReady)
{
_billingClient.StartConnection(this);
}
return taskInit;
}
#region IBillingClientStateListener
public void OnBillingServiceDisconnected()
{
Console.WriteLine($"Connection disconnected.");
_tcsInitialized?.TrySetResult(false);
_disconnectedAction?.Invoke();
}
public void OnBillingSetupFinished(BillingResult billingResult)
{
var responseCode = billingResult.ResponseCode;
var debugMessage = billingResult.DebugMessage;
if (responseCode == BillingResponseCode.Ok)
{
QuerySkuDetails();
QueryPurchases();
_tcsInitialized?.TrySetResult(true);
}
else
{
Console.WriteLine($"Failed connection {debugMessage}");
_tcsInitialized?.TrySetResult(false);
}
}
#endregion
#region ISkuDetailsResponseListener
public void OnSkuDetailsResponse(BillingResult billingResult, IList<SkuDetails> skuDetailsList)
{
if (billingResult == null)
{
Console.WriteLine("onSkuDetailsResponse: null BillingResult");
return;
}
var responseCode = billingResult.ResponseCode;
var debugMessage = billingResult.DebugMessage;
switch (responseCode)
{
case BillingResponseCode.Ok:
if (skuDetailsList == null)
{
_skusWithSkuDetails.Clear();
}
else
{
if (skuDetailsList.Count > 0)
{
ProductsInStore = new List<InAppBillingProduct>();
}
foreach (var skuDetails in skuDetailsList)
{
_skusWithSkuDetails.Add(skuDetails.Sku, skuDetails);
//ToDo.alfon. make use mapper here
ProductsInStore.Add(new InAppBillingProduct
{
Name = skuDetails.Title,
Description = skuDetails.Description,
ProductId = skuDetails.Sku,
CurrencyCode = skuDetails.PriceCurrencyCode,
LocalizedIntroductoryPrice = skuDetails.IntroductoryPrice,
LocalizedPrice = skuDetails.Price,
MicrosIntroductoryPrice = skuDetails.IntroductoryPriceAmountMicros,
MicrosPrice = skuDetails.PriceAmountMicros
});
}
}
break;
case BillingResponseCode.ServiceDisconnected:
case BillingResponseCode.ServiceUnavailable:
case BillingResponseCode.BillingUnavailable:
case BillingResponseCode.ItemUnavailable:
case BillingResponseCode.DeveloperError:
case BillingResponseCode.Error:
Console.WriteLine("onSkuDetailsResponse: " + responseCode + " " + debugMessage);
break;
case BillingResponseCode.UserCancelled:
Console.WriteLine("onSkuDetailsResponse: " + responseCode + " " + debugMessage);
break;
// These response codes are not expected.
case BillingResponseCode.FeatureNotSupported:
case BillingResponseCode.ItemAlreadyOwned:
case BillingResponseCode.ItemNotOwned:
default:
Console.WriteLine("onSkuDetailsResponse: " + responseCode + " " + debugMessage);
break;
}
}
#endregion
#region Helper Methods Private
private void ProcessPurchases(List<Purchase> purchasesList)
{
if (purchasesList == null)
{
Console.WriteLine("No purchases done.");
return;
}
if (IsUnchangedPurchaseList(purchasesList))
{
Console.WriteLine("Purchases has not changed.");
return;
}
_purchases.AddRange(purchasesList);
PurchasedProducts = _purchases.Select(sku => new InAppBillingPurchase
{
PurchaseToken = sku.PurchaseToken
})?.ToList();
if (purchasesList != null)
{
LogAcknowledgementStatus(purchasesList);
}
}
private bool IsUnchangedPurchaseList(List<Purchase> purchasesList)
{
// TODO: Optimize to avoid updates with identical data.
return false;
}
private void LogAcknowledgementStatus(List<Purchase> purchasesList)
{
int ack_yes = 0;
int ack_no = 0;
foreach (var purchase in purchasesList)
{
if (purchase.IsAcknowledged)
{
ack_yes++;
}
else
{
ack_no++;
}
}
//Log.d(TAG, "logAcknowledgementStatus: acknowledged=" + ack_yes +
// " unacknowledged=" + ack_no);
}
private void QuerySkuDetails()
{
var parameters = SkuDetailsParams
.NewBuilder()
.SetType(BillingClient.SkuType.Subs)
.SetSkusList(_skuList)
.Build();
_billingClient.QuerySkuDetailsAsync(parameters, this);
}
private void QueryPurchases()
{
if (!_billingClient.IsReady)
{
Console.WriteLine("queryPurchases: BillingClient is not ready");
}
var result = _billingClient.QueryPurchases(BillingClient.SkuType.Subs);
ProcessPurchases(result?.PurchasesList?.ToList());
}
#endregion
}

Camera Problems

I have run into a few problems when trying to get the camera to work accordingly... The camera Demo Works on the 8520 device (Has a memory Card) but does not work on the 9780 device (Has No Memory Card) the error given
ERROR Class java.lang.ArrayOutOfBoundsException :index 0>=0
My code Sample:
public class MyScreen extends MainScreen{
Player _p;
VideoControl _videoControl;
FileConnection fileconn;
String PATH;
String GetfileName;
LabelField GetPhotofileName = new LabelField("",LabelField.FOCUSABLE){
protected boolean navigationClick(int status, int time){
Dialog.alert("Clicked");
return true;
}
};
public static boolean SdcardAvailabulity() {
String root = null;
Enumeration e = FileSystemRegistry.listRoots();
while (e.hasMoreElements()) {
root = (String) e.nextElement();
if( root.equalsIgnoreCase("sdcard/") ) {
}else if( root.equalsIgnoreCase("store/") ) {
}
}
class MySDListener implements FileSystemListener {
public void rootChanged(int state, String rootName) {
if( state == ROOT_ADDED ) {
if( rootName.equalsIgnoreCase("sdcard/") ) {
}
} else if( state == ROOT_REMOVED ) {
}
}
}
return true;
}
protected boolean invokeAction(int action){
boolean handled = super.invokeAction(action);
if(SdcardAvailabulity()){
PATH = System.getProperty("fileconn.dir.memorycard.photos")+"Image_"+System.currentTimeMillis()+".jpg";//here "str" having the current Date and Time;
} else {
// PATH = System.getProperty("file:///store/home/user/pictures/")+"Image_"+System.currentTimeMillis()+".jpg";
PATH = System.getProperty("fileconn.dir.photos")+"Image_"+System.currentTimeMillis()+".jpg";
}
if(!handled){
if(action == ACTION_INVOKE){
try{
byte[] rawImage = _videoControl.getSnapshot(null);
System.out.println("----------1");
fileconn=(FileConnection)Connector.open(PATH);
System.out.println("----------2");
if(fileconn.exists()){
fileconn.delete();
System.out.println("----------3");
}
fileconn.create();
System.out.println("----------4");
OutputStream os=fileconn.openOutputStream();
System.out.println("----------5");
os.write(rawImage);
GetfileName =fileconn.getName();
System.out.println("----------6");
System.out.println("GetfileName----------"+GetfileName);
fileconn.close();
System.out.println("----------7");
os.close();
Status.show("Image is Captured",200);
GetPhotofileName.setText(GetfileName);
System.out.println("----------8");
if(_p!=null)
_p.close();
System.out.println("----------9");
}catch(Exception e){
if(_p!=null){
_p.close();
}
if(fileconn!=null){
try{
fileconn.close();
}catch (IOException e1){
//if the action is other than click the trackwheel(means go to the menu options) then we do nothing;
}
}
}
}
}
return handled;
}
public MyScreen(){
setTitle("Camera App");
try{
System.out.println("Debug------------10");
_p = javax.microedition.media.Manager.createPlayer("capture://video?encoding=jpeg&width=1024&height=768");
_p.realize();
_videoControl = (VideoControl) _p.getControl("VideoControl");
System.out.println("Debug------------11");
if (_videoControl != null){
Field videoField = (Field) _videoControl.initDisplayMode (VideoControl.USE_GUI_PRIMITIVE, "net.rim.device.api.ui.Field");
_videoControl.setDisplayFullScreen(true);
System.out.println("Debug------------12");
_videoControl.setVisible(true);
_p.start();
System.out.println("Debug------------13");
if(videoField != null){
add(videoField);
System.out.println("Debug------------14");
}
}
}catch(Exception e){
if(_p!=null) {
_p.close();
}
Dialog.alert(e.toString());
}
add(GetPhotofileName);
}
}
on the 8520 (Has a Memory Card) the code works fine on the 9780 (Has no Memory Card) the the code stops at "System.out.println("debug---1")", can anyone please tell me if you can see any problem with my code???
public static boolean SdcardAvailabulity() {
String root = null;
Enumeration e = FileSystemRegistry.listRoots();
while (e.hasMoreElements()) {
root = (String) e.nextElement();
if( root.equalsIgnoreCase("sdcard/") ) {
return true;
}else if( root.equalsIgnoreCase("store/") ) {
return false;
}
}
class MySDListener implements FileSystemListener {
public void rootChanged(int state, String rootName) {
if( state == ROOT_ADDED ) {
if( rootName.equalsIgnoreCase("sdcard/") ) {
}
} else if( state == ROOT_REMOVED ) {
}
}
}
return true;
}
This is the sollution, My "SD card availability" code only returned true which caused the picture not to save when the blackberry had no memory card inserted. # Eugen Martynov Please read through the code and you will see it is there :)

EF 4.1, database first and Many-to-Many relationships - How to get all sub-objects?

Let's say I have the following tables in a database forming a Many-to-Many Relationship. And in an ASP.Net MVC project using EF 4.1, I have corresponding POCO entities and a Repository layer to access the database.
People: PersonId PK, Firsname, Lastname
FavoriteRestaurants: ID PK, PersonId, RestaurantId
Restaurants: ResaurantId PK, Name
If I have a PersonId, what is the best way to list all this person's favorite restaurant names?
Or how would I do to initialise this Enumerable based on the person's Id using a repository layer?
IEnumerable MyFavoriteRestaurants = ???
I know I could use foreach to loop on the Person.FavoriteRestaurants collections an retrieve each FavoriteRestaurant.Restaurant one by one, but I was wondering if there were a more elegant way to do this in one line of code.
UPDATE
Here is an example of a Person POCO entity class in my project. This code has been generated by a Microsoft template downloaded from here:
http://visualstudiogallery.msdn.microsoft.com/23df0450-5677-4926-96cc-173d02752313/
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace UpDir.Domain
{
public partial class Person : EntityBase
{
#region Primitive Properties
public virtual int PersonId
{
get;
set;
}
public virtual string Firstname
{
get;
set;
}
public virtual string Middlename
{
get;
set;
}
public virtual string Lastname
{
get;
set;
}
public virtual string Nickname
{
get;
set;
}
public virtual string EncryptedEmail
{
get;
set;
}
public virtual string Photo
{
get;
set;
}
public virtual short StatusId
{
get { return _statusId; }
set
{
if (_statusId != value)
{
if (Status != null && Status.StatusId != value)
{
Status = null;
}
_statusId = value;
}
}
}
private short _statusId;
#endregion
#region Navigation Properties
public virtual ICollection<Member> Members
{
get
{
if (_members == null)
{
var newCollection = new FixupCollection<Member>();
newCollection.CollectionChanged += FixupMembers;
_members = newCollection;
}
return _members;
}
set
{
if (!ReferenceEquals(_members, value))
{
var previousValue = _members as FixupCollection<Member>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupMembers;
}
_members = value;
var newValue = value as FixupCollection<Member>;
if (newValue != null)
{
newValue.CollectionChanged += FixupMembers;
}
}
}
}
private ICollection<Member> _members;
public virtual ICollection<Message> Messages
{
get
{
if (_messages == null)
{
var newCollection = new FixupCollection<Message>();
newCollection.CollectionChanged += FixupMessages;
_messages = newCollection;
}
return _messages;
}
set
{
if (!ReferenceEquals(_messages, value))
{
var previousValue = _messages as FixupCollection<Message>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupMessages;
}
_messages = value;
var newValue = value as FixupCollection<Message>;
if (newValue != null)
{
newValue.CollectionChanged += FixupMessages;
}
}
}
}
private ICollection<Message> _messages;
public virtual ICollection<Notification> Notifications
{
get
{
if (_notifications == null)
{
var newCollection = new FixupCollection<Notification>();
newCollection.CollectionChanged += FixupNotifications;
_notifications = newCollection;
}
return _notifications;
}
set
{
if (!ReferenceEquals(_notifications, value))
{
var previousValue = _notifications as FixupCollection<Notification>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupNotifications;
}
_notifications = value;
var newValue = value as FixupCollection<Notification>;
if (newValue != null)
{
newValue.CollectionChanged += FixupNotifications;
}
}
}
}
private ICollection<Notification> _notifications;
public virtual Status Status
{
get { return _status; }
set
{
if (!ReferenceEquals(_status, value))
{
var previousValue = _status;
_status = value;
FixupStatus(previousValue);
}
}
}
private Status _status;
public virtual ICollection<UpDirEmail> FromEmails
{
get
{
if (_fromEmails == null)
{
var newCollection = new FixupCollection<UpDirEmail>();
newCollection.CollectionChanged += FixupFromEmails;
_fromEmails = newCollection;
}
return _fromEmails;
}
set
{
if (!ReferenceEquals(_fromEmails, value))
{
var previousValue = _fromEmails as FixupCollection<UpDirEmail>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupFromEmails;
}
_fromEmails = value;
var newValue = value as FixupCollection<UpDirEmail>;
if (newValue != null)
{
newValue.CollectionChanged += FixupFromEmails;
}
}
}
}
private ICollection<UpDirEmail> _fromEmails;
public virtual ICollection<UpDirEmail> ToEmails
{
get
{
if (_toEmails == null)
{
var newCollection = new FixupCollection<UpDirEmail>();
newCollection.CollectionChanged += FixupToEmails;
_toEmails = newCollection;
}
return _toEmails;
}
set
{
if (!ReferenceEquals(_toEmails, value))
{
var previousValue = _toEmails as FixupCollection<UpDirEmail>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupToEmails;
}
_toEmails = value;
var newValue = value as FixupCollection<UpDirEmail>;
if (newValue != null)
{
newValue.CollectionChanged += FixupToEmails;
}
}
}
}
private ICollection<UpDirEmail> _toEmails;
public virtual ICollection<UpDirEvent> UpDirEvents
{
get
{
if (_upDirEvents == null)
{
var newCollection = new FixupCollection<UpDirEvent>();
newCollection.CollectionChanged += FixupUpDirEvents;
_upDirEvents = newCollection;
}
return _upDirEvents;
}
set
{
if (!ReferenceEquals(_upDirEvents, value))
{
var previousValue = _upDirEvents as FixupCollection<UpDirEvent>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupUpDirEvents;
}
_upDirEvents = value;
var newValue = value as FixupCollection<UpDirEvent>;
if (newValue != null)
{
newValue.CollectionChanged += FixupUpDirEvents;
}
}
}
}
private ICollection<UpDirEvent> _upDirEvents;
#endregion
#region Association Fixup
private void FixupStatus(Status previousValue)
{
if (previousValue != null && previousValue.People.Contains(this))
{
previousValue.People.Remove(this);
}
if (Status != null)
{
if (!Status.People.Contains(this))
{
Status.People.Add(this);
}
if (StatusId != Status.StatusId)
{
StatusId = Status.StatusId;
}
}
}
private void FixupMembers(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Member item in e.NewItems)
{
item.Person = this;
}
}
if (e.OldItems != null)
{
foreach (Member item in e.OldItems)
{
if (ReferenceEquals(item.Person, this))
{
item.Person = null;
}
}
}
}
private void FixupMessages(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Message item in e.NewItems)
{
item.Person = this;
}
}
if (e.OldItems != null)
{
foreach (Message item in e.OldItems)
{
if (ReferenceEquals(item.Person, this))
{
item.Person = null;
}
}
}
}
private void FixupNotifications(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (Notification item in e.NewItems)
{
item.Person = this;
}
}
if (e.OldItems != null)
{
foreach (Notification item in e.OldItems)
{
if (ReferenceEquals(item.Person, this))
{
item.Person = null;
}
}
}
}
private void FixupFromEmails(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (UpDirEmail item in e.NewItems)
{
item.FromPerson = this;
}
}
if (e.OldItems != null)
{
foreach (UpDirEmail item in e.OldItems)
{
if (ReferenceEquals(item.FromPerson, this))
{
item.FromPerson = null;
}
}
}
}
private void FixupToEmails(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (UpDirEmail item in e.NewItems)
{
item.ToPerson = this;
}
}
if (e.OldItems != null)
{
foreach (UpDirEmail item in e.OldItems)
{
if (ReferenceEquals(item.ToPerson, this))
{
item.ToPerson = null;
}
}
}
}
private void FixupUpDirEvents(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (UpDirEvent item in e.NewItems)
{
item.Person = this;
}
}
if (e.OldItems != null)
{
foreach (UpDirEvent item in e.OldItems)
{
if (ReferenceEquals(item.Person, this))
{
item.Person = null;
}
}
}
}
#endregion
}
}
You don't need to think too much about that, EF will do it for you if you have defined your entity classes correct way like this,
Public class Person{
public int PersonId {get;set;}
public string Firsname{get;set;}
....
public virtual IList<Resturent> Resturents {get;set;}
}
Public class Restaurant{
public int ResaurantId {get;set;}
public string Name{get;set;}
....
public virtual IList<Resturent> People{get;set;}
}
Then you can simply access person.Restaurants to get all restaurants.
I finally figured it out. This is how I am doing it:
IEnumerable<Restaurants> MyFavoriteRestaurants = person.FavoriteRestaurants.Select(m => m.Restaurants);

Resources