How to log subsonic3 sql - sql

I'm starting to develop a new asp.net application based on subsonic3 (for queries) and log4net (for logs) and would like to know how to interface subsonic3 with log4net so that log4net logs the underlying sql used by subsonic.
This is what I have so far:
public static IEnumerable<arma_ocorrencium> ListArmasOcorrencia()
{
if (logger.IsInfoEnabled)
{
logger.Info("ListarArmasOcorrencia: start");
}
var db = new BdvdDB();
var select = from p in db.arma_ocorrencia
select p;
var results = select.ToList<arma_ocorrencium>(); //Execute the query here
if (logger.IsInfoEnabled)
{
// log sql here
}
if (logger.IsInfoEnabled)
{
logger.Info("ListarArmasOcorrencia: end");
}
return results;
}

You can use the Log property of the Provider class:
_db.Provider.Log = Console.Out;
will log your SQL statements to the console. If you want to use log4net or something similar you will have to write a small mediator class that implements TextWriter and redirects all received input to log4net.

You can get the generated sql like this:
string sql = select.GetQueryText();
Make sure you are using the version 3.0.0.4 or above.
Cheers

Related

Linq2DB Nlog or logging

is there a way to log all linq2DB sql queries that are made to he database with NLog?
I cannot find any realistic example. There is something for miniprofiler, but this doesn't help me, because I have not experience with it.
pull request
example
example 2
Inside your Setup method you could turn on Trace and setup WriteTraceLine to Console.WriteLine
[SetUp]
public void Setup()
{
LinqToDB.Data.DataConnection.TurnTraceSwitchOn();
LinqToDB.Data.DataConnection.WriteTraceLine = (message, displayName) => { Console.WriteLine($"{message} {displayName}"); };
}
This will write all executed SQL Queries (together with params) to the Console

How to fetch liferay entity through custom-finder in custom plugin portlet?

How can we fetch liferay entities through custom-finder using custom SQL?
Following is my sql query written in default.xml (I have trimmed down the query to the bare minimum so that the logic remains simple. Since it included a few functions and joins we couldn't use DynamicQuery API ):
SELECT
grp.*
FROM
Group_
WHERE
site = 1
AND active_ = 1
AND type_ <> 3
Relevant code in MyCustomGroupFinderImpl.java:
Session session = null;
try {
session = openSession();
// fetches the query string from the default.xml
String sql = CustomSQLUtil.get(FIND_ONLY_ACTIVE_SITES);
SQLQuery sqlQuery = session.createSQLQuery(sql);
sqlQuery.addEntity("Group_", GroupImpl.class);
// sqlQuery.addEntity("Group_", PortalClassLoaderUtil.getClassLoader().loadClass("com.liferay.portal.model.impl.GroupImpl"));
return (List<Group>) QueryUtil.list(sqlQuery, getDialect(), 0, QueryUtil.ALL_POS);
}
catch (Exception e) {
throw new SystemException(e);
}
finally {
closeSession(session);
}
This above code won't work as the GroupImpl class is present in portal-impl.jar and this jar cannot be used in custom portlet.
I also tried using sqlQuery.addEntity("Group_", PortalClassLoaderUtil.getClassLoader().loadClass("com.liferay.portal.model.impl.GroupImpl"))
But this above code throws exception:
com.liferay.portal.kernel.exception.SystemException:
com.liferay.portal.kernel.dao.orm.ORMException:
org.hibernate.MappingException:
Unknown entity: com.liferay.portal.model.impl.GroupImpl
But the same code works for our custom-entity, if we write sqlQuery.addEntity("MyCustomGroup", MyCustomGroupImpl.class);.
Thanks
I found out from the liferay forum thread that instead of session = openSession();
we would need to fetch the session from liferaySessionFactory as follows to make it work:
// fetch liferay's session factory
SessionFactory sessionFactory = (SessionFactory) PortalBeanLocatorUtil.locate("liferaySessionFactory");
Session session = null;
try {
// open session using liferay's session factory
session = sessionFactory.openSession();
// fetches the query string from the default.xml
String sql = CustomSQLUtil.get(FIND_ONLY_ACTIVE_SITES);
SQLQuery sqlQuery = session.createSQLQuery(sql);
// use portal class loader, since this is portal entity
sqlQuery.addEntity("Group_", PortalClassLoaderUtil.getClassLoader().loadClass("com.liferay.portal.model.impl.GroupImpl"));
return (List<Group>) QueryUtil.list(sqlQuery, getDialect(), 0, QueryUtil.ALL_POS);
}
catch (Exception e) {
throw new SystemException(e);
}
finally {
sessionFactory.closeSession(session); // edited as per the comment on this answer
// closeSession(session);
}
Hope this helps somebody on stackoverflow, also I found a nice tutorial regarding custom-sql which also uses the same approach.

How to easily convert .sdf developed in Vs 2010 to SQL Server database

I don't have SQL Server installed my machine. Hence I decided to start working with a SQL Server Compact Edition (.sdf) in VS2010. After then I installed SQL Server at the moment, now I'd like to convert from .sdf to a "real" SQL Server database.
How can I do it ? Please advise.
What you should to is to change your connectionString that points to your Compact SQL to your new SQL Server instance.
After that in you Context file, inside of a static constructor which is called:
static YourDbContext()
{
Database.SetInitializer(new CreateDatabaseIfNotExists<YourDbContext>());
}
This should create your database and tables based on your models. If you need to insert any data you should Enable-Migrations and in a configuration file that is createdc8 override Seed method.
One important thing DO NOT ASSUME that you have rights or privileges to CREATE or DROP DATABASE or to execute table modificiations.
I will assume that you used EF Code First approach. Your context file could look something like this:
public YourDbContext : DbContext
{
static YourDbContext()
{
// Database.SetInitializer<DbContext>(null); // Change this line to the next one
Database.SetInitializer(new CreateDatabaseIfNotExists<YourDbContext>());
}
// The rest of implementation
}
Inside of Visual Studio in Package Manager Console execute:
Enable-Migrations -ProjectName YourProjectName
(If you have more than one DbContext implementation you will need to follow the instructions from the error message that Enable-Migrations throws back at you.)
Once this is done you will notice a new folder Migrations with one file Configuration.cs. Open it and you will see method Seed.
protected override void Seed(YourDbContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
// Here you can call your context.DbSetImplementation.Add(new Something {...});
}
That's about it.

How to get the sql update method generated by LinqToSql?

How to get the sql generated by LinqToSql for update method?
I use the following code to show the sql generated by LinqToSql in VS2008's debug output window, but it only gets the sql select method generated,
how can I find the sql update method that was generated by LinqToSql?
I know the Sql Server Profiler and LinqPad can get it(the sql-update generated), but I want to show them in VS2008 or Log them to a file.
public partial class Linq2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
DemoDataContext ctx = new DemoDataContext ();
// Then attach it to the Log property of your DataContext...
ctx.Log = new DebugTextWriter();
var product = ctx.Products.FirstOrDefault();
product.ProductName = "NewName1";
ctx.SubmitChanges();
}
}
// Add this class somewhere in your project...
public class DebugTextWriter : System.IO.TextWriter
{
public override void Write(char[] buffer, int index, int count)
{
System.Diagnostics.Debug.Write(new String(buffer, index, count));
}
public override void Write(string value)
{
System.Diagnostics.Debug.Write(value);
}
public override Encoding Encoding
{
get { return System.Text.Encoding.Default; }
}
}
And I get the sql-select query in the VS2008 debug output window:
SELECT TOP (1) [t0].[Id], [t0].[ProductName] ……
FROM [dbo].[Products] AS [t0]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1
Your Database context object has a Log method that you can override. Your full Update statement, and every SQL command generated by Linq-To-SQL, can be captured via this Log method. I know this works because I use it to capture all our queries in our app. Just keep in mind that L2S can send a fair amount of output to the Log method, so make sure to capture it all. Your Update statement is in there somewhere.
Thank you for all answers.
I have found Linq To Sql Profiler to solve the problem.

Access SQL Server 2008 Change Tracking Info via Entity Framework

Based on this link it looks like I can get date inserted / date modified information "for free" (without the need for triggers etc.) using Sql Server 2008 by simply enabling Change Tracking. I am using Entity Framework to access the data. My question is, how do I access date modified / date inserted information for the database records via Entity Framework and LINQ?
I'm using VS2008 so I don't have the new EF v4 stuff yet (but if it can be done in the new EF please let me know).
Thanks.
Aw, nevermind. I found it plenty easy to just create the Inserted and LastModified columns in each table myself, set a default value for each, and build an update trigger for LastModified. That seems to be what people do, and the Change Tracking looks like it's mainly set up for sync'ing. Right?
OK, this works beautifully (also see this article)...
public partial class MyEntities
{
partial void OnContextCreated()
{
this.SavingChanges += new System.EventHandler(CustomSavingChangesLogic);
}
/// <summary>
/// Apply timestamps
/// </summary>
public void CustomSavingChangesLogic(object sender, System.EventArgs e)
{
var changedEntities = ((ObjectContext)sender).ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified);
foreach (var stateEntryEntity in changedEntities)
{
if(!stateEntryEntity.IsRelationship) {
var entity = stateEntryEntity.Entity;
var lastModifiedPropInfo = entity.GetType().GetProperty("LastModified");
if (lastModifiedPropInfo != null)
lastModifiedPropInfo.SetValue(entity, DateTime.UtcNow, null);
if (stateEntryEntity.State == EntityState.Added)
{
var createdPropInfo = entity.GetType().GetProperty("Created");
if (createdPropInfo != null)
createdPropInfo.SetValue(entity, DateTime.UtcNow, null);
}
}
}
}
}