Diskuze: Problém se spouštěním aplikace na jiném PC
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.


Michal Štěpánek:18.12.2016 16:49
Zkontroloval jsi architekturu (32-64), Framework, umístění databáze, atd...?
Maros2470:18.12.2016 17:14
Zkontroloval architekturu mám AnyCPU, Framework 4.5 a databáze 2012 express. Zobrazí se kontrolky, ale jen ty pevně zadané. Ty co jsou vytvářeny dynamicky už ne, nenajede čas a zobrazené kontrolky jsou bez odezvy.
Michal Štěpánek:18.12.2016 17:19
Místo "AnyCPU" používej "x86". Nevím proč, někde mi to taky někdo poradil, když mi něco nechtělo fungovat... Když jsem appku zkompiloval místo AnyCPU na x86, začalo mi to fungovat dobře...
Marian Benčat:18.12.2016 18:05
Toto je dosti divne. Pri anycpu funguje kod jak v 32 tak 64bit modu vicemene
bez problemu.Jedin co me napada je pouziti nejakeho unmanaged kodu v nejake
knihovne, co je delane pro 32bit, ale je oznacena jako x64 DLL. Tezkok rict
Maros2470:18.12.2016 18:16
Zapnul jsem analýzu kódu při sestavení a zobrazuje se mi toto:
Závažnost Kód Popis Projekt Soubor Řádek Stav potlačení
Upozornění CA1001 Implementujte IDisposable na 'BaseViewModel', protože
vytváří členy následujících typů IDisposable: 'BirthdayContext'. Pokud
'BaseViewModel' byl dříve dodán, přidání nových členů, které
implementují IDisposable do tohoto typu, je považováno za rozbíjející
změny stávajícím příjemcům. Birthday(2017)
D:\Programování\2016\WPF\Birthday(2017)\Birthday(2017)\ViewModels\BaseViewModel.cs
9 Aktivní
Může to být tímto?
Michal Štěpánek:18.12.2016 18:17
Taky jsem si to myslel, že anycpu je i na 32 i na 64, ale nechtělo mi fungovat spojení a celkově i komunikace s DB. Když kompiluji na x86, funguje mi to na obou architekturách.
Maros2470:18.12.2016 18:45
Zapnul jsem analýzu kódu při sestavení a zobrazuje se mi toto:
Závažnost Kód Popis Projekt Soubor Řádek Stav potlačení
Upozornění CA1001 Implementujte IDisposable na 'BaseViewModel', protože
vytváří členy následujících typů IDisposable: 'BirthdayContext'. Pokud
'BaseViewModel' byl dříve dodán, přidání nových členů, které
implementují IDisposable do tohoto typu, je považováno za rozbíjející
změny stávajícím příjemcům. Birthday(2017)
D:\Programování\2016\WPF\Birthday(2017)\Birthday(2017)\ViewModels\BaseViewModel.cs
9 Aktivní
Může to být tímto?
Ty ve ViewModelu vytváříš DBcontext? :-/
No, asi tu nechceš hodnotit kod, tak ti jen odpovim.. Timto to nebude, to je jen upozornění na případné neuvolnění unmanaged resourcu.. jako jsou SQL connection, transakce atp.
Prostě neimplementovaný IDisposable interface. Herceg za to trhá ruce, ale program bude fungovat i stím = tímto to není.
Maros2470:18.12.2016 19:18
Raději ten BaseViewModel pošlu. Přidávám i čitelnější obrázek nastavení.
using Birthday_2017_.Models;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data.Entity;
namespace Birthday_2017_.ViewModels
{
public class BaseViewModel : INotifyPropertyChanged
{
public bool _canExecute;
BirthdayContext context = new BirthdayContext();
public BaseViewModel()
{
_canExecute = true;
FillOfficeEmail(); FillOfficeFax(); FillOfficeGsm(); FillOfficePhone(); FillOfficeVoip(); FillOfficeWeb(); FillPerson(); FillPhoto(); FillPostAdress();
FillPrivateAdress(); FillPrivateEmail(); FillPrivateFax(); FillPrivateGsm(); FillPrivatePhone(); FillPrivateVoip(); FillPrivateWeb(); FillVideo(); FillZipCode();
}
public ObservableCollection<OfficeEmailTab> OfficeEmailTabs { get; set; }
public ObservableCollection<OfficeFaxTab> OfficeFaxTabs { get; set; }
public ObservableCollection<OfficeGsmTab> OfficeGsmTabs { get; set; }
public ObservableCollection<OfficePhoneTab> OfficePhoneTabs { get; set; }
public ObservableCollection<OfficeVoipTab> OfficeVoipTabs { get; set; }
public ObservableCollection<OfficeWebTab> OfficeWebTabs { get; set; }
public ObservableCollection<PersonTab> PersonTabs { get; set; }
public ObservableCollection<PhotoTab> PhotoTabs { get; set; }
public ObservableCollection<PostAdressTab> PostAdressTabs { get; set; }
public ObservableCollection<PrivateAdressTab> PrivateAdressTabs { get; set; }
public ObservableCollection<PrivateEmailTab> PrivateEmailTabs { get; set; }
public ObservableCollection<PrivateFaxTab> PrivateFaxTabs { get; set; }
public ObservableCollection<PrivateGsmTab> PrivateGsmTabs { get; set; }
public ObservableCollection<PrivatePhoneTab> PrivatePhoneTabs { get; set; }
public ObservableCollection<PrivateVoipTab> PrivateVoipTabs { get; set; }
public ObservableCollection<PrivateWebTab> PrivateWebTabs { get; set; }
public ObservableCollection<ZipCodeTab> ZipCodeTabs { get; set; }
public ObservableCollection<VideoTab> VideoTabs { get; set; }
private void FillOfficeEmail() { context.OfficeEmailTabs.Load(); OfficeEmailTabs = context.OfficeEmailTabs.Local; }
private void FillOfficeFax() { context.OfficeFaxTabs.Load(); OfficeFaxTabs = context.OfficeFaxTabs.Local; }
private void FillOfficeGsm() { context.OfficeGsmTabs.Load(); OfficeGsmTabs = context.OfficeGsmTabs.Local; }
private void FillOfficePhone() { context.OfficePhoneTabs.Load(); OfficePhoneTabs = context.OfficePhoneTabs.Local; }
private void FillOfficeVoip() { context.OfficeVoipTabs.Load(); OfficeVoipTabs = context.OfficeVoipTabs.Local; }
private void FillOfficeWeb() { context.OfficeWebTabs.Load(); OfficeWebTabs = context.OfficeWebTabs.Local; }
private void FillPerson() { context.PersonTabs.Load(); PersonTabs = context.PersonTabs.Local; }
private void FillPhoto() { context.PhotoTabs.Load(); PhotoTabs = context.PhotoTabs.Local; }
private void FillPostAdress() { context.PostAdressTabs.Load(); PostAdressTabs = context.PostAdressTabs.Local; }
private void FillPrivateAdress() { context.PrivateAdressTabs.Load(); PrivateAdressTabs = context.PrivateAdressTabs.Local; }
private void FillPrivateEmail() { context.PrivateEmailTabs.Load(); PrivateEmailTabs = context.PrivateEmailTabs.Local; }
private void FillPrivateFax() { context.PrivateFaxTabs.Load(); PrivateFaxTabs = context.PrivateFaxTabs.Local; }
private void FillPrivateGsm() { context.PrivateGsmTabs.Load(); PrivateGsmTabs = context.PrivateGsmTabs.Local; }
private void FillPrivatePhone() { context.PrivatePhoneTabs.Load(); PrivatePhoneTabs = context.PrivatePhoneTabs.Local; }
private void FillPrivateVoip() { context.PrivateVoipTabs.Load(); PrivateVoipTabs = context.PrivateVoipTabs.Local; }
private void FillPrivateWeb() { context.PrivateWebTabs.Load(); PrivateWebTabs = context.PrivateWebTabs.Local; }
private void FillVideo() { context.VideoTabs.Load(); VideoTabs = context.VideoTabs.Local; }
private void FillZipCode() { context.ZipCodeTabs.Load(); ZipCodeTabs = context.ZipCodeTabs.Local; }
//Selected OfficeEmailTab
private OfficeEmailTab _selectedOfficeEmail;
public OfficeEmailTab SelectedOfficeEmail { get { return _selectedOfficeEmail; } set { _selectedOfficeEmail = value; NotifyPropertyChanged("SelectedOfficeEmail"); } }
//Selected OfficeFaxTab
private OfficeFaxTab _selectedOfficeFax;
public OfficeFaxTab SelectedOfficeFax { get { return _selectedOfficeFax; } set { _selectedOfficeFax = value; NotifyPropertyChanged("SelectedOfficeFax"); } }
//Selected OfficeGsmTab
private OfficeGsmTab _selectedOfficeGsm;
public OfficeGsmTab SelectedOfficeGsm { get { return _selectedOfficeGsm; } set { _selectedOfficeGsm = value; NotifyPropertyChanged("SelectedOfficeGsm"); } }
//Selected OfficePhoneTab
private OfficePhoneTab _selectedOfficePhone;
public OfficePhoneTab SelectedOfficePhone { get { return _selectedOfficePhone; } set { _selectedOfficePhone = value; NotifyPropertyChanged("SelectedOfficePhone"); } }
//Selected OfficeVoipTab
private OfficeVoipTab _selectedOfficeVoip;
public OfficeVoipTab SelectedOfficeVoip { get { return _selectedOfficeVoip; } set { _selectedOfficeVoip = value; NotifyPropertyChanged("SelectedOfficeVoip"); } }
//Selected OfficeWebTab
private OfficeWebTab _selectedOfficeWeb;
public OfficeWebTab SelectedOfficeWeb { get { return _selectedOfficeWeb; } set { _selectedOfficeWeb = value; NotifyPropertyChanged("SelectedOfficeWeb"); } }
//Selected PersonTab
private PersonTab _selectedPerson;
public PersonTab SelectedPerson { get { return _selectedPerson; } set { _selectedPerson = value; NotifyPropertyChanged("SelectedPerson"); } }
//Selected PhotoTab
private PhotoTab _selectedPhoto;
public PhotoTab SelectedPhoto { get { return _selectedPhoto; } set { _selectedPhoto = value; NotifyPropertyChanged("SelectedPhoto"); } }
//Selected PostAdressTab
private PostAdressTab _selectedPostAdress;
public PostAdressTab SelectedPostAdress { get { return _selectedPostAdress; } set { _selectedPostAdress = value; NotifyPropertyChanged("SelectedPostAdress"); } }
//Selected PrivateAdressTab
private PrivateAdressTab _selectedPrivateAdress;
public PrivateAdressTab SelectedPrivateAdress { get { return _selectedPrivateAdress; } set { _selectedPrivateAdress = value; NotifyPropertyChanged("SelectedPrivateAdress"); } }
//Selected PrivateEmailTab
private PrivateEmailTab _selectedPrivateEmail;
public PrivateEmailTab SelectedPrivateEmail { get { return _selectedPrivateEmail; } set { _selectedPrivateEmail = value; NotifyPropertyChanged("SelectedPrivateEmail"); } }
//Selected PrivateFaxTab
private PrivateFaxTab _selectedPrivateFax;
public PrivateFaxTab SelectedPrivateFax { get { return _selectedPrivateFax; } set { _selectedPrivateFax = value; NotifyPropertyChanged("SelectedPrivateFax"); } }
//Selected PrivateGsmTab
private PrivateGsmTab _selectedPrivateGsm;
public PrivateGsmTab SelectedPrivateGsm { get { return _selectedPrivateGsm; } set { _selectedPrivateGsm = value; NotifyPropertyChanged("SelectedPrivateGsm"); } }
//Selected PrivatePhoneTab
private PrivatePhoneTab _selectedPrivatePhone;
public PrivatePhoneTab SelectedPrivatePhone { get { return _selectedPrivatePhone; } set { _selectedPrivatePhone = value; NotifyPropertyChanged("SelectedPrivatePhone"); } }
//Selected PrivateVoipTab
private PrivateVoipTab _selectedPrivateVoip;
public PrivateVoipTab SelectedPrivateVoip { get { return _selectedPrivateVoip; } set { _selectedPrivateVoip = value; NotifyPropertyChanged("SelectedPrivateVoip"); } }
//Selected PrivateWebTab
private PrivateWebTab _selectedPrivateWeb;
public PrivateWebTab SelectedPrivateWeb { get { return _selectedPrivateWeb; } set { _selectedPrivateWeb = value; NotifyPropertyChanged("SelectedPrivateWeb"); } }
//Selected VideoTab
private VideoTab _selectedVideo;
public VideoTab SelectedVideo { get { return _selectedVideo; } set { _selectedVideo = value; NotifyPropertyChanged("SelectedVideo"); } }
//Selected ZipCodeTab
private ZipCodeTab _selectedZipCode;
public ZipCodeTab SelectedZipCode { get { return _selectedZipCode; } set { _selectedZipCode = value; NotifyPropertyChanged("SelectedZipCode"); } }
// Refresh
public void RefreshOfficeEmail() { NotifyPropertyChanged("SelectedOfficeEmail"); }
public void RefreshOfficeFax() { NotifyPropertyChanged("SelectedOfficeFax"); }
public void RefreshOfficeGsm() { NotifyPropertyChanged("SelectedOfficeGsm"); }
public void RefreshOfficePhone() { NotifyPropertyChanged("SelectedOfficePhone"); }
public void RefreshOfficeVoip() { NotifyPropertyChanged("SelectedOfficeVoip"); }
public void RefreshOfficeWeb() { NotifyPropertyChanged("SelectedOfficeWeb"); }
public void RefreshPerson() { NotifyPropertyChanged("SelectedPerson"); }
public void RefreshPhoto() { NotifyPropertyChanged("SelectedPhoto"); }
public void RefreshPostAdress() { NotifyPropertyChanged("SelectedPostAdress"); }
public void RefreshPrivateAdress() { NotifyPropertyChanged("SelectedPrivateAdress"); }
public void RefreshPrivateEmail() { NotifyPropertyChanged("SelectedPrivateEmail"); }
public void RefreshPrivateFax() { NotifyPropertyChanged("SelectedPrivateFax"); }
public void RefreshPrivateGsm() { NotifyPropertyChanged("SelectedPrivateGsm"); }
public void RefreshPrivatePhone() { NotifyPropertyChanged("SelectedPrivatePhone"); }
public void RefreshPrivateVoip() { NotifyPropertyChanged("SelectedPrivateVoip"); }
public void RefreshPrivateWeb() { NotifyPropertyChanged("SelectedPrivateWeb"); }
public void RefreshVideo() { NotifyPropertyChanged("SelectedVideo"); }
public void RefreshZipCode() { NotifyPropertyChanged("SelectedZipCode"); }
// RefreshAll
public void RefreshAll()
{
RefreshOfficeEmail();
RefreshOfficeFax();
RefreshOfficeGsm();
RefreshOfficePhone();
RefreshOfficeVoip();
RefreshOfficeWeb();
RefreshPerson();
RefreshPhoto();
RefreshPostAdress();
RefreshPrivateAdress();
RefreshPrivateEmail();
RefreshPrivateFax();
RefreshPrivateGsm();
RefreshPrivatePhone();
RefreshPrivateVoip();
RefreshPrivateWeb();
RefreshVideo();
RefreshZipCode();
}
public string Back
{
get
{
return "Zpět";
}
}
public string Home
{
get
{
return "Domů";
}
}
public string Exit
{
get
{
return "Konec";
}
}
// Save
public void Save() { context.SaveChanges(); }
/// <summary>
/// INotifyPropertyChanged
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string property)
{
if (property == null)
throw new ArgumentNullException("property");
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
Marian Benčat:18.12.2016 19:34
Nejdříve to hlavní, co tě zajímá.. Zkontroloval bych si, kam se snaží připojit ten Entity framework, je ta databáze vůbec dostupná? Nepolykáš tam někde výjimku na Timeout?
Mimochodem.. sjou 3 ruzne zpusoby jak handlit Entity Framework DB Context u desktopové aplikace.. Nejhorší je mít to jako singleton od startu aplikac až dokonce, horší je mít to "per view - viewmodel" jak máš ty. V jednom okně totiž můžeš mít třeba 10Viewček, k ním 10 Viewmodelu = máš 10x DBContext, každý má vlastní interní reprezentace identity mapy, vlastní connection, vlastní read-commited transakci:
Pokud ti tedy můžu poradit k tvému problému, zkontroloval bych, ejstli jsi vubec na tom druhem PC navázat connection.. Osobně vidím problém tam.
Další rada co ti dám. Nedávej DBContext do ViewModelu. Udělej si něco jako UOW. Ale správně,.. né tak na hovno, jak o to má Microsoft v příkladech, (https://www.asp.net/…-application) ale pořádně.
Maros2470:18.12.2016 19:57
No jsem amatér, začátečník. Jak můžu zkontrolovat jestli na tom druhém PC je navázán connection?
Na jakou db je ten DBContext vůbec napojený?
A mas na tom druhym PC SQLServer express local db?
Maros2470:18.12.2016 20:10
<connectionStrings>
<add name="BirthdayContext" connectionString="metadata=res://*/Models.BirthdayModel.csdl|res://*/Models.BirthdayModel.ssdl|res://*/Models.BirthdayModel.msl;provider=System.Data.SqlClient;provider connection string="data source=(LocalDB)\MSSQLLocalDB;attachdbfilename=|DataDirectory|\Data\BirthdayData.mdf;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
Maros2470:18.12.2016 20:13
Instaloval jsem jí, ale bude asi problém v tom. Zkusil jsem jinou apku, která tam běhala a dělá to samé.
Takze je to SQL 2014. Musi byt 2014+ i na tom druhým PC. 2012 má jiný connection string.
Maros2470:19.12.2016 12:49
Nemá náhodou VS 2015 community nějaká omezení? Nainstaloval jsem je na druhém PC a zkusil mimo ladění spustit apku a to se stejným výsledkem. VS je přitom stejné a SQL taky.
Asi to nie je najsuper riesenie, ale ja prave kvoli tymto problemom nepouzivam db, ale xml subory.
Maros2470:19.12.2016 13:51
Uvažoval jsem už o tom. Můžeš mi poslat nějaký odkaz na práci s xml? Databázi mám celkem rozvětvenou a nevím jak na to.
Libor Šimo (libcosenior):19.12.2016 13:57
Je to tu niekde v serialoch c#. Pracujes normalne s observablecollection a
najdi si tu serializaciu a deserializaciu.
Pre mna bolo dost velkou vyhodou, ze data som si dal do excelovskej tabulky a tu
som prekonvertoval so xml.
Maros2470:19.12.2016 14:05
A řeší xml i vazby mezi třídami? Například na třídu Person jsou vázány třídy OfficeAdress a PrivateAdress a na ně zase ZipCode atd.
Samozrejme.
Libor Šimo (libcosenior):19.12.2016 14:20
Vlastne ako databazu pouzijes xml subory, budes ich naplnat, prepisovat, mazat ... a data z nich pouzivat v aplikacii. Potom (nie som profik a nikto ma to neucil) ich mam ulozene v zlozke, kde mam exe subor appky.
Michal Štěpánek:19.12.2016 16:29
Ukládat data do stejné složky jako appka není dobrý nápad (resp. je to dost špatný nápad), protože pak musíš ošetřovat povolení k zápisu do toho souboru. Většinou se appka dává do Program Files, kde není (z bezpečnostního hlediska správně) standardně povolen zápis. Povolovat zápis do Program Files (byť jen třeba do složky s konkrétním programem) velmi nedoporučuji, bo uživatelé jsou nevyzpytatelní a jsou schopni zničit a zrušit cokoliv, k čemu mají práva... Proto by takové soubory měly být třeba v Program Data, nebo AppData (přesně na to tam tyto složky jsou)...
Libor Šimo (libcosenior):19.12.2016 16:43
Este nikdy som nerobil appku, ktora by sa instalovala, pretoze neviem
ako.
Ak mozes, porad.
Michal Štěpánek:19.12.2016 17:04
Na tvorbu instalátoru používám InnoSetup, přijde mi (aspoň pro moje schopnosti a možnosti) nejlepší. Nicméně aplikace, které dělám pro naše firemní použití, nasazuji prostým kopírováním složek. To ovšem nic nemění na úložišti souborů...
Libor Šimo (libcosenior):19.12.2016 17:06
Prave ze mam appku, ktoru chcem poslal viacerym uzivatelom a nemam moznost im
to osobne nakopirovat.
Je nejaky navod na pouzitie InnoSetup-u?
Libor Šimo (libcosenior):19.12.2016 17:11
Diky, uz som nasiel dokonca tu od Davida.
Ja pouzivam Install Shield LE:
http://learn.flexerasoftware.com/…isual-Studio
Nebo taky Advanced Installer
Michal Štěpánek:19.12.2016 23:56
Mám pocit, že Compact edition už není podporována, místo toho je právě ta LocalDB
Maros2470:20.12.2016 9:51
Compact funguje, dokonce jsem celou apku předělal, ale výsledek je stejný. Na jiných PC to neběhá. Načte MainWindow a kontrolky, ale ty nereagují, pouze se objevují Tooltipy a jsou načteny styly. Jakoby to nekomunikovalo s ViewModely.
Michal Štěpánek:20.12.2016 10:14
Zkus si udělat nějakou kontrolou na připojení k DB, třeba MessageBox ještě před načtením komponent do okna...
Maros2470:20.12.2016 10:29
Já si myslím, že problém je v tom, že mám view a view modely ve složkách a ty nezkompiluje
Maros2470:20.12.2016 10:54
Na něco jsem asi přišel. Zkusil jsem publikovat apku a vyšlo mi toto (viz. obrázek). Chybí tam databáze, a Entity dll, i když v sestavení je vidím.
Michal Štěpánek:20.12.2016 11:00
A když si zobrazíš vlastnosti těch souborů, jsou nastaveny, že se mají kopírovat do kompilační ho adresáře? Nebo jsou nastaveny nějak jinak, než ty soubory, které jsou správně?
Zobrazeno 50 zpráv z 80.