Using LINQ to SharePoint between site collections

Short answer

Ensure that the SPContext is null before making the request as:

 try 
{
// Clear the SPContext by setting HttpContext to null
HttpContext.Current = null;
// Execute LINQ
IQueryable<Post> results = null;
string path = "http://othersitecollection/subweb/";
using (LinqDataContext context = new LinqDataContext(path))
{
results = context.Posts.Where(p => p.Id > 1)
.OrderByDescending(p => p.Published).Take(3);
this.PostsRepeater.DataSource = results;
this.PostsRepeater.DataBind();
}
}
finally
{
// Restore context
HttpContext.Current = httpContext;
}

Optionally, you can only clear the context if you are sure you are going cross site collections as this would improve performance.

Long answer

LINQ to SharePoint uses the constructor within DataContext to set the request URL of the data query. Under the hood, this looks like:

 public DataContext(string requestUrl) 
{
this.Web = requestUrl;
this.ObjectTrackingEnabled = true;
this.DeferredLoadingEnabled = true;
this.EntityTracker = new EntityTracker(this);
this.LoadedLists = new Dictionary<string, Dictionary<Type, LoadedList>>();
}

Note that the property "this.Web” is set. If we analyze that parameter, it is used by get_DataConnection as:

 internal SPDataConnection get_DataConnection() 
{
if (this.dataConnection == null)
{
this.dataConnection = new SPServerDataConnection(this.Web);
}
return this.dataConnection;
}

The constructor of SPServerDataConnection checks if SPContext is null.

 public SPServerDataConnection(string url) 
{
if (SPContext.Current != null)
{
this.defaultSite = SPContext.Current.Site;
this.defaultWeb = (SPContext.Current.Web.Url == url)
? SPContext.Current.Web : this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
}
else
{
this.defaultSite = new SPSite(url);
this.defaultWeb = this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
}
if (!this.defaultWeb.Exists)
{
throw new ArgumentException(Resources.GetString(
"CannotFindWeb", new object[] { url }));
}
this.defaultWebUrl = this.defaultWeb.ServerRelativeUrl;
this.openedWebs = new Dictionary<string, SPWeb>();
this.openedWebs.Add(this.defaultWebUrl, this.defaultWeb);
}

Therefore, since SPContext required HttpContext, we will enter the “else” section of the constructor and we can access data cross site collections.