I have this code where I compare the values of oldState object by the currentState in fluent inhibernate, what I want is to log the property that has been changed and its value,here I get the new and the old values but I waant also to get the property name.
if I reflect #event.Entity I can get all the properties and their values so is there any way to get the property name by its value.
public void OnPostUpdate(NHibernate.Event.PostUpdateEvent #event)
{
var entityToAudit = #event.Entity as IAuditable;
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AuditLog.txt");
using (StreamWriter sw = File.AppendText(path))
{
for (int i = 0; i < #event.OldState.Length; i++)
{
if (#event.OldState[i] != null)
{
if (!#event.OldState[i].Equals(#event.State[i]))
{
sw.WriteLine("the value has ben changed from " + #event.OldState[i] + " to " + #event.State[i]);
}
}
else
{
if (#event.State[i] != null)
{
sw.WriteLine("the value has ben changed from being empty to " + #event.State[i]);
}
}
}
}
}
You don't need to use System.Reflection for that. PostUpdateEvent already contains all the property names in the order you need :
var propertyName = e.Persister.PropertyNames[i];
Related
I have this c# code where i am trying to get data from a wsdl in visual studio .
The code is okay but when i try to get the data to written on notepad it just shows an empty space :
WindowsService1.ServiceReference1.GetModifiedBookingsOperationResponse getModbkgsResp;
using (var proxy = new WindowsService1.ServiceReference1.InventoryServiceClient())
{
int noofBookings = 1;
getModbkgsResp = proxy.GetModifiedBookings(getModBkgsReq);
WindowsService1.ServiceReference1.Booking[] bookings = new WindowsService1.ServiceReference1.Booking[noofBookings];
getModbkgsResp.Bookings = new WindowsService1.ServiceReference1.Booking[noofBookings];
getModbkgsResp.Bookings = bookings;
if (getModbkgsResp.Bookings != null)
{
for (int i = 0; i < bookings.Length; i++)
{
Booking bk = new WindowsService1.ServiceReference1.Booking();
getModbkgsResp.Bookings[i] = bk;
if (bk != null )
{
bookingSource = bk.BookingSource;
if (bk.BookingId == Bookingcode)
{
this.WriteToFile("Booking Source =" + bookingSource + "");
}
else
{
this.WriteToFile("Sorry could not find your source of booking");
}
}
else
{
this.WriteToFile("Looks like source is null " );
}
}
}
else
{
this.WriteToFile("ERROR: Booking details not returned from GetModifiedBookings! " +StartDate);
}
}
I'm not sure why you are using the new keyword to create items that should have been retrieved from the service. Naturally anything created with new will be initialized with default values and will not contain any data that was retrieved from the service.
My guess is your code should look more like this:
using (var proxy = new WindowsService1.ServiceReference1.InventoryServiceClient())
{
var response = proxy.GetModifiedBookings(getModBkgsReq);
if (response.Bookings == null)
{
this.WriteToFile("ERROR: Booking details not returned from GetModifiedBookings! " +StartDate);
return;
}
var booking = response.Bookings.SingleOrDefault( b => b.BookingId == bookingCode);
if (booking == null)
{
this.WriteToFile("Sorry could not find your source of booking");
return;
}
var bookingSource = booking.BookingSource;
this.WriteToFile("Booking Source =" + bookingSource + "");
}
I want to use the below list globally in my aspx page whose name is lstUMSGroupDetails. Currently I am getting its value from a function.
I want to use that list values in other functions too. SO how should I make it global.
its code is below
private void Get_AuthenticateUser_Ums(string strUName)
{
string strCurrentGroupName = "";
int intCurrentGroupID = 0;
try
{
if (!string.IsNullOrEmpty(strUName))
{
List<IPColoBilling.App_Code.UMS.UMSGroupDetails> lstUMSGroupDetails = null;
List<IPColoBilling.App_Code.UMS.UMSLocationDetails> lstUMSLocationDetails = null;
objGetUMS.GetUMSGroups(strUserName, out strCurrentGroupName, out intCurrentGroupID, out lstUMSLocationDetails, out lstUMSGroupDetails);
if (strCurrentGroupName != "" && intCurrentGroupID != 0)
{
strCurrentGrp = strCurrentGroupName;
intCurrentGrpId = intCurrentGroupID;
}
else
{
Response.Redirect("~/NotAuthorize.aspx", false);
}
}
}
catch (Exception ex)
{
string strErrorMsg = ex.Message.ToString() + " " + "StackTrace :" + ex.StackTrace.ToString();
CommonDB.WriteLog("ERROR:" + strErrorMsg, ConfigurationManager.AppSettings["IPCOLO_LOG"].ToString());
}
You can store it in Session.
Session["lstUMSGroupDetails"] = lstUMSGroupDetails;
Then you can get this by.
List<IPColoBilling.App_Code.UMS.UMSGroupDetails> lstUMSGroupDetails = (List<IPColoBilling.App_Code.UMS.UMSGroupDetails>)Session["lstUMSGroupDetails"];
For more information please see MSDN Reference.
Could you not assign it to a slot in the Session Dictionary?
For example:
var myList = new List<int>();
Session["groups"] = myList;
I use the nhibernate interceptor to compare values of the old state and the current state of the entity properties but some of the properties are of type ICollection so could anyone guide me about how to check if an object is of type ICollection
this is my code
public void OnPostUpdate(NHibernate.Event.PostUpdateEvent #event)
{
var entityToAudit = #event.Entity as IAuditable;
string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "AuditLog.txt");
using (StreamWriter sw = File.AppendText(path))
{
for (int i = 0; i < #event.OldState.Length; i++)
{
string propertyName = #event.Persister.PropertyNames[i];
if (#event.OldState[i] != null)
{
if (!#event.OldState[i].Equals(#event.State[i]))
{
sw.WriteLine("the value of "+ propertyName + " has been changed from " + #event.OldState[i] + " to " + #event.State[i]);
}
}
else
{
if (#event.State[i] != null)
{
sw.WriteLine("the value of "+ propertyName + " has been changed from being empty to " + #event.State[i]);
}
}
}
}
}
You have more than one options to do this, use is or use as with null checking:
if (obj is ICollection){
//your logic
}
Or, if you need the object as ICollection later on, I recommend to use as:
var icoll = obj as ICollection
if (icoll != null){
//use icoll
//icoll.Something();
}
you can check the type using a simple is
like this:
var obj = getObject();
if(obj is TypeYouWant)
doSomething();
Good Luck
I need to override SaveChanges() so that I can update a column (NewClub.LastActivityDate) when certain entities get modified. The problem is that many times the table (NewClub) that has LastActivityDate is not in the entity set being presented to SaveChanges() so I need a way to update NewClub.LastActivityDate if it's in the entity set or not.
Here is what I have so far.
Thanks for looking
public override int SaveChanges()
{
var saveSuccess = false;
var newClubPrimaryKeyId = 0;
ObjectContext ctx = ((IObjectContextAdapter)this).ObjectContext;
List<ObjectStateEntry> objectStateEntryList =
ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added
| EntityState.Unchanged // need this to get to NewClub when it's not the table being updated
| EntityState.Modified
| EntityState.Deleted).ToList();
foreach (ObjectStateEntry entry in objectStateEntryList)
{
//Skip over relationships
if (entry.IsRelationship) continue;
//Make sure the entity is a member of the NCO schema: NewClub[...]
if (SecurityHelper.IsValidNewClubTableName(entry.EntitySet.Name))
{
entityInfoStr += "Entity Name: " + entry.EntitySet.Name + " Entity State: " + entry.State;
var nc = entry.Entity as NewClub;
var ncp = entry.Entity as NewClubProspect;
if (nc != null) { newClubPrimaryKeyId = nc.Id; }
else if (ncp != null){newClubPrimaryKeyId = ncp.NewClubId;}
//... More comparisons here....
//---------------------------------------------------------------
//Update NewClub.LastActivityDate where Id == newClubPrimaryKeyId
//----------------------------------------------------------------
//This does not work
string q = #"UPDATE NewClub SET LastActivityDate=" + DateTime.Now + " WHERE Id=" +
newClubPrimaryKeyId;
var t = ctx.CreateQuery<NewClub>(q);
}
}
try
{
saveSuccess = base.SaveChanges() > 0;
}
catch (Exception e)
{
string ex = e.ToString();
}
return saveSuccess ? 1 : 0;
}
You don't need to manually write a SQL query for this, the entry object gives you access to the current and last state of your object.
Try something like this
foreach( var entry in objectStateEntryList)
{
var lastTime = entry.Property("LastActivityDate");
if(lastTime != null)
{
lastTime.CurrentValue = DateTime.Now;
lastTime.IsModified = true; // be careful with this, throws exception if object is added not modified
}
}
You may also want to check out EFHooks https://github.com/visoft/EFHooks
I want to read properties of MSI in C# in desktop application.I am using following code:
public static string GetMSIProperty( string msiFile, string msiProperty)
{
string retVal= string.Empty ;
Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Object installerObj = Activator.CreateInstance(classType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
Database database = installer.OpenDatabase("C:\\DataP\\sqlncli.msi",0 );
string sql = String.Format("SELECT Value FROM Property WHERE Property=’{0}’", msiProperty);
View view = database.OpenView(sql);
Record record = view.Fetch();
if (record != null)
{
retVal = record.get_StringData(1);
}
else
retVal = "Property Not Found";
return retVal;
}
But I am getting error as System.Runtime.InteropServices.COMException was unhandled.
the sqlncli.msi file is physically placed at c:\DataP location. While debugging I found that database does not contain the data after installer.OpenDatabase() statement.
How can I resolve this issue and get MSI properties in C#?
Windows Installer XML's Deployment Tools Foundation (WiX DTF) is an Open Source project from Microsoft which includes the Microsoft.Deployment.WindowsInstaller MSI interop library. It's far easier and more reliable to use this to do these sorts of queries. It even has a LINQ to MSI provider that allows you to treat MSI tables as entities and write queries against them.
using System;
using System.Linq;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using(var database = new QDatabase(#"C:\tfs\iswix.msi", DatabaseOpenMode.ReadOnly))
{
var properties = from p in database.Properties
select p;
foreach (var property in properties)
{
Console.WriteLine("{0} = {1}", property.Property, property.Value);
}
}
using (var database = new Database(#"C:\tfs\iswix.msi", DatabaseOpenMode.ReadOnly))
{
using(var view = database.OpenView(database.Tables["Property"].SqlSelectString))
{
view.Execute();
foreach (var rec in view) using (rec)
{
Console.WriteLine("{0} = {1}", rec.GetString("Property"), rec.GetString("Value"));
}
}
}
Console.Read();
}
}
}
I did it in following way:
String inputFile = #"C:\\Rohan\\sqlncli.msi";
// Get the type of the Windows Installer object
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
// Create the Windows Installer object
WindowsInstaller.Installer installer = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
// Open the MSI database in the input file
Database database = installer.OpenDatabase(inputFile, 0);
// Open a view on the Property table for the version property
View view = database.OpenView("SELECT * FROM _Tables");
// Execute the view query
view.Execute(null);
// Get the record from the view
Record record = view.Fetch();
while (record != null)
{
Console.WriteLine(record.get_StringData(0) + '=' + record.get_StringData(1) + '=' + record.get_StringData(2) + '=' + record.get_StringData(3));
record = view.Fetch();
}
And its working for me.
The SQL string is incorrect. It should be:
SELECT `Value` FROM `Property` WHERE `Property`.`Property` = ’{0}’
I was trying to re-use this code, and the only change I had to make to get the code posted by Devashri to work is this line:
string sql = String.Format("SELECT `Value` FROM `Property` WHERE `Property`='{0}'", msiProperty);
Watch out for the single quotes!
as of 04/2020 it would be
Type installerType { get; set; }
WindowsInstaller.Installer installerObj { get; set; }
...
installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
installerObj = (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
var installer = installerObj as WindowsInstaller.Installer;
...
private void lnkSelectMsi_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
WindowsInstaller.Database msiDatabase = installerObj.OpenDatabase(txtMsiPath.Text, 0);
readMsiTableColumn(msiDatabase, cmbTable.Text, cmbColumn.Text);
}
private void readMsiTableColumn(WindowsInstaller.Database msiDatabase, string table)
{
WindowsInstaller.View msiView = null;
Record record = null;
string s = string.Empty;
try
{
msiView = msiDatabase.OpenView($"Select * from _Columns");
msiView.Execute();
record = msiView.Fetch();
int k = 0;
while (record != null)
{
if (record.StringData[1].Equals(table, StringComparison.OrdinalIgnoreCase))
{
k++;
s += $"{record.StringData[3],-50} ";
}
record = msiView.Fetch();
}
s += nl;
s += "".PadRight(50 * k, '-') + nl;
msiView.Close();
msiView = msiDatabase.OpenView($"Select * from {table}");
msiView.Execute();
record = msiView.Fetch();
while (record != null)
{
string recordValue = string.Empty;
for (int i = 1; i < record.FieldCount + 1; i++)
{
try { recordValue += $"{record.StringData[i],-50} "; }
catch (Exception ex) { recordValue += $"{i}. err {ex.Message}; "; }
}
s += recordValue + nl;
record = msiView.Fetch();
}
msiView.Close();
txtRes.Text = s;
}
catch (Exception ex) { txtRes.Text = ex.Message; }
}