Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/NHibernate.Test/Async/Linq/QueryReadOnlyTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by AsyncGenerator.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------


using System.Linq;
using NHibernate.Linq;
using NUnit.Framework;

namespace NHibernate.Test.Linq
{
using System.Threading.Tasks;
[TestFixture]
public class QueryReadOnlyTestsAsync : LinqTestCase
{
[Test]
public async Task CanSetReadOnlyOnLinqQueriesAsync()
{
var result = await ((from e in db.Customers
where e.CompanyName == "Bon app'"
select e).WithOptions(o => o.SetReadOnly(true)).ToListAsync());

Assert.That(result.All(x => session.IsReadOnly(x)), Is.True);
}

[Test]
public async Task CanSetReadOnlyOnLinqPagingQueryAsync()
{
var result = await ((from e in db.Customers
select e).Skip(1).Take(1).WithOptions(o => o.SetReadOnly(true)).ToListAsync());

Assert.That(result.All(x => session.IsReadOnly(x)), Is.True);
}

[Test]
public async Task CanSetReadOnlyBeforeSkipOnLinqOrderedPageQueryAsync()
{
var result = await ((from e in db.Customers
orderby e.CompanyName
select e).WithOptions(o => o.SetReadOnly(true)).Skip(5).Take(5).ToListAsync());

Assert.That(result.All(x => session.IsReadOnly(x)), Is.True);
}
}
}
39 changes: 39 additions & 0 deletions src/NHibernate.Test/Linq/QueryReadOnlyTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Linq;
using NHibernate.Linq;
using NUnit.Framework;

namespace NHibernate.Test.Linq
{
[TestFixture]
public class QueryReadOnlyTests : LinqTestCase
{
[Test]
public void CanSetReadOnlyOnLinqQueries()
{
var result = (from e in db.Customers
where e.CompanyName == "Bon app'"
select e).WithOptions(o => o.SetReadOnly(true)).ToList();

Assert.That(result.All(x => session.IsReadOnly(x)), Is.True);
}

[Test]
public void CanSetReadOnlyOnLinqPagingQuery()
{
var result = (from e in db.Customers
select e).Skip(1).Take(1).WithOptions(o => o.SetReadOnly(true)).ToList();

Assert.That(result.All(x => session.IsReadOnly(x)), Is.True);
}

[Test]
public void CanSetReadOnlyBeforeSkipOnLinqOrderedPageQuery()
{
var result = (from e in db.Customers
orderby e.CompanyName
select e).WithOptions(o => o.SetReadOnly(true)).Skip(5).Take(5).ToList();

Assert.That(result.All(x => session.IsReadOnly(x)), Is.True);
}
}
}
2 changes: 1 addition & 1 deletion src/NHibernate/Async/Linq/DefaultQueryProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public Task<int> ExecuteDmlAsync<T>(QueryMode queryMode, Expression expression,
var query = Session.CreateQuery(nhLinqExpression);

SetParameters(query, nhLinqExpression.ParameterValuesByName);
ApplyOptions(query);
_options?.Apply(query);
return query.ExecuteUpdateAsync(cancellationToken);
}
catch (Exception ex)
Expand Down
22 changes: 2 additions & 20 deletions src/NHibernate/Linq/DefaultQueryProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,30 +175,12 @@ protected virtual NhLinqExpression PrepareQuery(Expression expression, out IQuer
}

SetParameters(query, nhLinqExpression.ParameterValuesByName);
ApplyOptions(query);
_options?.Apply(query);
SetResultTransformerAndAdditionalCriteria(query, nhLinqExpression, nhLinqExpression.ParameterValuesByName);

return nhLinqExpression;
}

private void ApplyOptions(IQuery query)
{
if (_options == null)
return;

if (_options.Timeout.HasValue)
query.SetTimeout(_options.Timeout.Value);

if (_options.Cacheable.HasValue)
query.SetCacheable(_options.Cacheable.Value);

if (_options.CacheMode.HasValue)
query.SetCacheMode(_options.CacheMode.Value);

if (_options.CacheRegion != null)
query.SetCacheRegion(_options.CacheRegion);
}

protected virtual object ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery)
{
IList results = query.List();
Expand Down Expand Up @@ -279,7 +261,7 @@ public int ExecuteDml<T>(QueryMode queryMode, Expression expression)
var query = Session.CreateQuery(nhLinqExpression);

SetParameters(query, nhLinqExpression.ParameterValuesByName);
ApplyOptions(query);
_options?.Apply(query);
return query.ExecuteUpdate();
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/NHibernate/Linq/IQueryableOptions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
using System;

namespace NHibernate.Linq
{
// Methods signatures taken from IQuery.
/// <summary>
/// Expose NH queryable options.
/// </summary>
//Since v5.1
[Obsolete("Please use NhQueryableOptions instead.")]
public interface IQueryableOptions
{
/// <summary>
Expand All @@ -29,7 +33,7 @@ public interface IQueryableOptions
IQueryableOptions SetCacheMode(CacheMode cacheMode);

/// <summary>
/// The timeout for the underlying ADO query.
/// Set the timeout for the underlying ADO query.
/// </summary>
/// <param name="timeout">The timeout in seconds.</param>
/// <returns><see langword="this"/> (for method chaining).</returns>
Expand Down
111 changes: 100 additions & 11 deletions src/NHibernate/Linq/NhQueryableOptions.cs
Original file line number Diff line number Diff line change
@@ -1,45 +1,134 @@
namespace NHibernate.Linq
{
public class NhQueryableOptions: IQueryableOptions
/// <summary>
/// Expose NH queryable options.
/// </summary>
public class NhQueryableOptions
#pragma warning disable 618
: IQueryableOptions
#pragma warning restore 618
{
protected internal bool? Cacheable { get; private set; }
protected internal CacheMode? CacheMode{ get; private set; }
protected internal string CacheRegion { get; private set; }
protected internal int? Timeout { get; private set; }
protected bool? Cacheable { get; private set; }
protected CacheMode? CacheMode { get; private set; }
protected string CacheRegion { get; private set; }
protected int? Timeout { get; private set; }
protected bool? ReadOnly { get; private set; }

public IQueryableOptions SetCacheable(bool cacheable)
#pragma warning disable 618
/// <inheritdoc />
IQueryableOptions IQueryableOptions.SetCacheable(bool cacheable) => SetCacheable(cacheable);

/// <inheritdoc />
IQueryableOptions IQueryableOptions.SetCacheMode(CacheMode cacheMode) => SetCacheMode(cacheMode);

/// <inheritdoc />
IQueryableOptions IQueryableOptions.SetCacheRegion(string cacheRegion) => SetCacheRegion(cacheRegion);

/// <inheritdoc />
IQueryableOptions IQueryableOptions.SetTimeout(int timeout) => SetTimeout(timeout);
#pragma warning restore 618

/// <summary>
/// Enable caching of this query result set.
/// </summary>
/// <param name="cacheable">Should the query results be cacheable?</param>
/// <returns><see langword="this"/> (for method chaining).</returns>
public NhQueryableOptions SetCacheable(bool cacheable)
{
Cacheable = cacheable;
return this;
}

public IQueryableOptions SetCacheMode(CacheMode cacheMode)
/// <summary>
/// Override the current session cache mode, just for this query.
/// </summary>
/// <param name="cacheMode">The cache mode to use.</param>
/// <returns><see langword="this"/> (for method chaining).</returns>
public NhQueryableOptions SetCacheMode(CacheMode cacheMode)
{
CacheMode = cacheMode;
return this;
}

public IQueryableOptions SetCacheRegion(string cacheRegion)
/// <summary>
/// Set the name of the cache region.
/// </summary>
/// <param name="cacheRegion">The name of a query cache region, or <see langword="null" />
/// for the default query cache</param>
/// <returns><see langword="this"/> (for method chaining).</returns>
public NhQueryableOptions SetCacheRegion(string cacheRegion)
{
CacheRegion = cacheRegion;
return this;
}

public IQueryableOptions SetTimeout(int timeout)
/// <summary>
/// Set the timeout for the underlying ADO query.
/// </summary>
/// <param name="timeout">The timeout in seconds.</param>
/// <returns><see langword="this"/> (for method chaining).</returns>
public NhQueryableOptions SetTimeout(int timeout)
{
Timeout = timeout;
return this;
}

internal NhQueryableOptions Clone()
/// <summary>
/// Set the read-only mode for entities (and proxies) loaded by this query. This setting
/// overrides the default setting for the session (see <see cref="ISession.DefaultReadOnly" />).
/// </summary>
/// <remarks>
/// <para>
/// Read-only entities can be modified, but changes are not persisted. They are not
/// dirty-checked and snapshots of persistent state are not maintained.
/// </para>
/// <para>
/// When a proxy is initialized, the loaded entity will have the same read-only setting
/// as the uninitialized proxy, regardless of the session's current setting.
/// </para>
/// <para>
/// The read-only setting has no impact on entities or proxies returned by the criteria
/// that existed in the session before the criteria was executed.
/// </para>
/// </remarks>
/// <param name="readOnly">
/// If <c>true</c>, entities (and proxies) loaded by the query will be read-only.
/// </param>
/// <returns><c>this</c> (for method chaining)</returns>
public NhQueryableOptions SetReadOnly(bool readOnly)
{
ReadOnly = readOnly;
return this;
}

protected internal NhQueryableOptions Clone()
{
return new NhQueryableOptions
{
Cacheable = Cacheable,
CacheMode = CacheMode,
CacheRegion = CacheRegion,
Timeout = Timeout
Timeout = Timeout,
ReadOnly = ReadOnly
};
}

protected internal void Apply(IQuery query)
{
if (Timeout.HasValue)
query.SetTimeout(Timeout.Value);

if (Cacheable.HasValue)
query.SetCacheable(Cacheable.Value);

if (CacheMode.HasValue)
query.SetCacheMode(CacheMode.Value);

if (CacheRegion != null)
query.SetCacheRegion(CacheRegion);

if (ReadOnly.HasValue)
query.SetReadOnly(ReadOnly.Value);
}
}
}