Depending on your database, this might work:
var banners = Database.Banners.Where(b => b.IsPublish.Value &&
b.Category.Value == (int) CategoryBanner.Banner &&
b.PeriodShowCountAlready < b.PeriodShowCount ||
b.ShowNext < DateTime.Now );
Then just skip a random number of banners...
var skip = new Random().Next(banners.Count() - 1);
var banner = banners.Skip(skip).FirstOrDefault();
As Amar points out, this is approach is less than optimal since it causes two trips to the databank. From my own experience profiling, the round-trip to another server most often costs much-much more than executing a simple SQL statement.
So, what options are there?
Fetch the entire set, and select a random banner locally. This is not optimal because the set might be very large. If you know the set to be small (less than 1000 records without binary fields [like the banner image], or less than 10k all in all should be negligible)
Ask the database how many object there are first, and then ask the database for the n:th object. This is bad because it causes two trips.
Make the database do everything, which entrails leaving the comfort of your ORM and writing a stored procedure manually. To that end you utilize newid() [on sql server] as order by parameter and everything is fast and good, but you have to do this on the server and not in your C# app.