static System.Security.Cryptography.RandomNumberGenerator RandomNumberGenerator = null;
/// <summary>
/// 回傳大於等於 0 小於 1
/// </summary>
/// <returns></returns>
public static double NextDouble()
{
if (RandomNumberGenerator == null || LastRandomGenerateTime < DateTime.Now.AddMinutes(-1))
{
RandomNumberGenerator = System.Security.Cryptography.RandomNumberGenerator.Create();
}
// Generate four random bytes
byte[] four_bytes = new byte[4];
RandomNumberGenerator.GetBytes(four_bytes);
// Convert the bytes to a UInt32
uint scale = BitConverter.ToUInt32(four_bytes, 0);
// And use that to pick a random number >= min and < max
// 0 <= (scale / (uint.MaxValue + 1.0)) < 1
return scale / (uint.MaxValue + 1.0);
}
/// <summary>
/// 回傳值介於 min ~ (max - 1)
/// </summary>
/// <param name="min"></param>
/// <param name="max"></param>
/// <returns></returns>
public static int GetRandomInt(int min, int max)
{
if(max < min)
{
throw new Exception("最大值不可小於最小值");
}
// Generate four random bytes
byte[] four_bytes = new byte[4];
RandomNumberGenerator.GetBytes(four_bytes);
// And use that to pick a random number >= min and < max
return (int)(min + (max - min) * NextDouble()); //因為 NextDouble 會小於 1,所以用無條件捨去.
}
/// <summary>
/// 產生 0 ~ (max - 1) 的亂數
/// </summary>
/// <param name="max"></param>
/// <returns></returns>
public static int GetRandomInt(int max)
{
return GetRandomInt(0, max);
}
/// <summary>
/// 產生 0 ~ (int.MaxValue - 1) 的亂數
/// </summary>
/// <returns></returns>
public static int GetRandomInt()
{
return GetRandomInt(int.MaxValue);
}
int tries = 0;
while (tries < Su.PgSql.maxTransactionAborted)
{
try
{
using (var scop = new System.Transactions.TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
var context = ShopBandContext.Context;
updateCount = await context.UpdateAsync<MarketDiscount>(dto, Sc.ModifyInfo,
onlyColumns: "StartAt,EndAt,NewPrice,FrontEndMemo,BackEndMemo");
scop.Complete();
break; //這個 Break 很重要
}
}
catch (Exception ex)
{
// 我發現因為是非同步模式,所以要檢查很多層的 InnerException
if (tries < Su.PgSql.maxTransactionAborted
&& ((ex.InnerException != null && ex.InnerException is Npgsql.PostgresException && ((Npgsql.PostgresException)ex.InnerException).SqlState == "40001")
|| (ex.InnerException.InnerException != null && ex.InnerException.InnerException is Npgsql.PostgresException && ((Npgsql.PostgresException)ex.InnerException.InnerException).SqlState == "40001")))
{
//隨機休息 10 ~ 20 ms, 等另一個 job 完工
System.Threading.Thread.Sleep(Su.MathUtil.Random.Next(10, 20));
tries++;
}
else
{
throw;
}
}
}
var combineBody = Expression.AndAlso(e1.Body, Expression.Invoke(e2, e1.Parameters[0]));
var finalExpression = Expression.Lambda<Func<TestClass, bool>>(combineBody, e1.Parameters).Compile();
public static class ExpressionExtension
{
public static Expression<Func<T, bool>> AndAlso<T>(this Expression<Func<T, bool>> e1, Expression<Func<T, bool>> e2)
{
var combineE = Expression.AndAlso(e1.Body, Expression.Invoke(e2, e1.Parameters[0]));
return Expression.Lambda<Func<T, bool>>(combineE, e1.Parameters);
}
public static Expression<Func<T, bool>> OrElse<T>(this Expression<Func<T, bool>> e1, Expression<Func<T, bool>> e2)
{
var combineE = Expression.OrElse(e1.Body, Expression.Invoke(e2, e1.Parameters[0]));
return Expression.Lambda<Func<T, bool>>(combineE, e1.Parameters);
}
}
Expression<Func<Market, bool>> e1 = e => e.Is_Deleted == isDelete;
Expression<Func<Market, bool>> e2 = e => string.IsNullOrEmpty(marketNo) || e.MarketNo.ToUpper().Contains(marketNo.ToUpper());
return new
{
andMarkets = Ds.PageContext.ShopBandContext.Markets.Where(e1.AndAlso(e2)).ToList(),
orMarkets = Ds.PageContext.ShopBandContext.Markets.Where(e1.OrElse(e2)).ToList(),
};
public static Expression<Func<T, bool>> OrElseAll<T>(this IEnumerable<Expression<Func<T, bool>>> exps)
{
if (exps.Count() == 1)
{
return exps.First();
}
var e0 = exps.First();
var orExp = exps.Skip(1).Aggregate(e0.Body, (x, y) => Expression.OrElse(x, Expression.Invoke(y, e0.Parameters[0])));
return Expression.Lambda<Func<T, bool>>(orExp, e0.Parameters);
}
public static Expression<Func<T, bool>> AndAlsoAll<T>(this IEnumerable<Expression<Func<T, bool>>> exps)
{
if (exps.Count() == 1)
{
return exps.First();
}
var e0 = exps.First();
var orExp = exps.Skip(1).Aggregate(e0.Body, (x, y) => Expression.AndAlso(x, Expression.Invoke(y, e0.Parameters[0])));
return Expression.Lambda<Func<T, bool>>(orExp, e0.Parameters);
}
Expression<Func<Market, bool>> q = e =>
e.Is_Deleted == "N"
&& (string.IsNullOrEmpty(marketNo) || e.MarketNo.ToLower().Contains(marketNo.ToLower()))
&& (string.IsNullOrEmpty(isCombination) || isCombination != "Y" || e.TypeEnum == 200);
if (!string.IsNullOrEmpty(name))
{
var nameList = name.Split(',').Select(e => e.Trim())
.Where(e => !string.IsNullOrEmpty(e));
if (nameList.Any())
{
q = q.AndAlso(nameList
.Select(s => (Expression<Func<Market, bool>>)(e => e.Name.ToLower().Contains(s.ToLower())))
.OrElseAll());
}
}
internal class MergeTool : ExpressionVisitor
{
private readonly ParameterExpression _parameter;
protected override Expression VisitParameter(ParameterExpression node)
{
return base.VisitParameter(_parameter);
}
internal MergeTool(ParameterExpression parameter)
{
_parameter = parameter;
}
public static Expression<Func<T, bool>> MergedExpression<T>(Expression<Func<T, bool>> e1, Expression<Func<T, bool>> e2)
{
ParameterExpression param = Expression.Parameter(typeof(T));
BinaryExpression MergeBody = Expression.AndAlso(e1.Body, e2.Body);
var ReplacedBody = (BinaryExpression)new MergeTool(param).Visit(MergeBody);
return Expression.Lambda<Func<T, bool>>(ReplacedBody, param);
}
}
使用時要 Compile
var mergedExpression = MergeTool.MergedExpression(e1, e2);
var list = testList.Where(mergedExpression.Compile());
<configuration>
<system.webServer>
<security>
<requestFiltering>
<hiddenSegments>
<add segment=".svn" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
public static void UpdateTableCache()
{
//標記自已是正在執行的 Thread. 讓舊的 Thread 在執行完畢之後, 應該會自動結束. 以防舊的 Thread 執行超過 10 秒.
CurrentThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
try
{
//確認自已是正在執行的 Thread, 重覆執行. (另一個 Thread 插入執行)
while (CurrentThreadId == System.Threading.Thread.CurrentThread.ManagedThreadId)
{
LastUpdateDate = DateTime.Now;
foreach (var dbId in CachedDbs)
{
var sql = @"select * from table_monitor";
var dt = Su.PgSql.DtFromSql(sql, dbId);
foreach (DataRow row in dt.Rows)
{
string changeId = row["update_count"].DBNullToDefault();
string CacheKey = TableCacheKey(dbId, row["table_name"].DBNullToDefault());
ObjectCache cache = MemoryCache.Default;
string OldValue = (string)cache[CacheKey];
if (OldValue == null)
{
cache.Set(CacheKey, changeId, DateTime.MaxValue);
}
else
{
if (changeId != OldValue)
{
cache.Remove(CacheKey);
cache.Set(CacheKey, changeId, DateTime.MaxValue);
}
}
}
}
//每兩秒檢查一次
System.Threading.Thread.Sleep(2000);
}
}
catch (Exception)
{
//依經驗, 只要 DB 能通, 這裡幾乎不會有問題, 所以這裡暫時不處理, 未來有問題時可以考慮寫入文字檔比較好.
}
}