Создайте службу переднего плана с флагом START_STICKY
.
@Override
public int onStartCommand(Intent startIntent, int flags, int startId) {
if (startIntent != null) {
String action = startIntent.getAction();
String command = startIntent.getStringExtra(CMD_NAME);
if (ACTION_CMD.equals(action)) {
if (CMD_PAUSE.equals(command)) {
if (mPlayback != null && mPlayback.isPlaying()) {
handlePauseRequest();
}
} else if (CMD_PLAY.equals(command)) {
ArrayList
Затем это можно вызвать из любой активности для воспроизведения музыки
Intent intent = new Intent(MusicService.ACTION_CMD, fileUrlToPlay, activity, MusicService::class.java)
intent.putParcelableArrayListExtra(MusicService.ARG_QUEUE, tracks)
intent.putExtra(MusicService.ARG_INDEX, position)
intent.putExtra(MusicService.CMD_NAME, MusicService.CMD_PLAY)
activity.startService(intent)
. Вы можете привязываться к службы с помощью bindService и сделать паузу / остановку службы из соответствующих методов жизненного цикла активности.
Вот хороший учебник о Воспроизведение музыки в фоновом режиме на Android
Невозможно создать отношения «многие ко многим» с персонализированной таблицей соединений. В отношениях «многие ко многим» EF управляет таблицей соединений внутри и снаружи. Это таблица без класса Entity в вашей модели. Чтобы работать с такой таблицей соединений с дополнительными свойствами, вам нужно будет создать фактически два отношения «один ко многим». Это может выглядеть так:
public class Member
{
public int MemberID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<MemberComment> MemberComments { get; set; }
}
public class Comment
{
public int CommentID { get; set; }
public string Message { get; set; }
public virtual ICollection<MemberComment> MemberComments { get; set; }
}
public class MemberComment
{
[Key, Column(Order = 0)]
public int MemberID { get; set; }
[Key, Column(Order = 1)]
public int CommentID { get; set; }
public virtual Member Member { get; set; }
public virtual Comment Comment { get; set; }
public int Something { get; set; }
public string SomethingElse { get; set; }
}
Если теперь вы хотите найти все комментарии членов с LastName
= «Смит», например, вы можете написать такой запрос:
var commentsOfMembers = context.Members
.Where(m => m.LastName == "Smith")
.SelectMany(m => m.MemberComments.Select(mc => mc.Comment))
.ToList();
... или ...
var commentsOfMembers = context.MemberComments
.Where(mc => mc.Member.LastName == "Smith")
.Select(mc => mc.Comment)
.ToList();
Или создать список членов с именем «Смит» (мы предполагаем, что их более одного) вместе с их комментариями вы можете использовать project:
var membersWithComments = context.Members
.Where(m => m.LastName == "Smith")
.Select(m => new
{
Member = m,
Comments = m.MemberComments.Select(mc => mc.Comment)
})
.ToList();
Если вы хотите найти все комментарии члена с MemberId
= 1:
var commentsOfMember = context.MemberComments
.Where(mc => mc.MemberId == 1)
.Select(mc => mc.Comment)
.ToList();
Теперь вы также можете фильтровать по свойствам в вашем соединении table (что было бы невозможно во многих отношениях), например: Отфильтровать все комментарии элемента 1, которые имеют свойство 99 в Something
:
var filteredCommentsOfMember = context.MemberComments
.Where(mc => mc.MemberId == 1 && mc.Something == 99)
.Select(mc => mc.Comment)
.ToList();
Из-за ленивой загрузки все может стать проще. Если у вас есть загруженный Member
, вы можете получить комментарии без эксплицитного запроса:
var commentsOfMember = member.MemberComments.Select(mc => mc.Comment);
Я полагаю, что ленивая загрузка будет автоматически получать комментарии за кулисами.
Изменить
Просто для удовольствия еще несколько примеров, как добавить сущности и отношения и как их удалить в этой модели:
1) Создайте один участник и два комментария этого участника :
var member1 = new Member { FirstName = "Pete" };
var comment1 = new Comment { Message = "Good morning!" };
var comment2 = new Comment { Message = "Good evening!" };
var memberComment1 = new MemberComment { Member = member1, Comment = comment1,
Something = 101 };
var memberComment2 = new MemberComment { Member = member1, Comment = comment2,
Something = 102 };
context.MemberComments.Add(memberComment1); // will also add member1 and comment1
context.MemberComments.Add(memberComment2); // will also add comment2
context.SaveChanges();
2) Добавить третий комментарий участника1:
var member1 = context.Members.Where(m => m.FirstName == "Pete")
.SingleOrDefault();
if (member1 != null)
{
var comment3 = new Comment { Message = "Good night!" };
var memberComment3 = new MemberComment { Member = member1,
Comment = comment3,
Something = 103 };
context.MemberComments.Add(memberComment3); // will also add comment3
context.SaveChanges();
}
3) Создать новый член и связать его с существующим комментарием2:
var comment2 = context.Comments.Where(c => c.Message == "Good evening!")
.SingleOrDefault();
if (comment2 != null)
{
var member2 = new Member { FirstName = "Paul" };
var memberComment4 = new MemberComment { Member = member2,
Comment = comment2,
Something = 201 };
context.MemberComments.Add(memberComment4);
context.SaveChanges();
}
4) Создайте связь между существующим элементом2 и комментарием 3:
var member2 = context.Members.Where(m => m.FirstName == "Paul")
.SingleOrDefault();
var comment3 = context.Comments.Where(c => c.Message == "Good night!")
.SingleOrDefault();
if (member2 != null && comment3 != null)
{
var memberComment5 = new MemberComment { Member = member2,
Comment = comment3,
Something = 202 };
context.MemberComments.Add(memberComment5);
context.SaveChanges();
}
5) Удалите это отношение еще раз:
var memberComment5 = context.MemberComments
.Where(mc => mc.Member.FirstName == "Paul"
&& mc.Comment.Message == "Good night!")
.SingleOrDefault();
if (memberComment5 != null)
{
context.MemberComments.Remove(memberComment5);
context.SaveChanges();
}
6) Удалите член1 и все его отношения к Комментарии:
var member1 = context.Members.Where(m => m.FirstName == "Pete")
.SingleOrDefault();
if (member1 != null)
{
context.Members.Remove(member1);
context.SaveChanges();
}
Это также удаляет отношения в MemberComments
, потому что отношения «один ко многим» между Member
и MemberComments
и между Comment
и MemberComments
настроены с каскадным удалить по соглашению. И это происходит потому, что MemberId
и CommentId
в MemberComment
обнаружены как свойства внешнего ключа для свойств навигации Member
и Comment
, и поскольку свойства FK имеют тип, не имеющий значения null int
, отношение , который, наконец, вызывает каскадное удаление-установку. Я думаю, что имеет смысл в этой модели.
Один из способов решить эту ошибку - поместить атрибут ForeignKey
поверх свойства, которое вы хотите в качестве внешнего ключа, и добавить свойство навигации.
Примечание. В атрибуте ForeignKey
между скобками и двойными кавычками, поместите имя класса, упомянутого таким образом.
[/g0]
Для тех, кто пришел сюда, интересно узнать, как получить отношение «многие ко многим» с столбцами атрибутов для отображения в файле EF .edmx (так как в настоящее время он не отображается и не рассматривается как набор навигационных свойств), И вы сгенерировали эти классы из своей таблицы базы данных (или, по-моему, сначала базы данных в MS lingo).
Удалите 2 таблицы (вопрос OP, член и комментарий ) в вашем .edmx и добавить их снова через «Сгенерировать модель из базы данных». (т. е. не пытайтесь обновить Visual Studio - удалить, сохранить, добавить, сохранить)
Затем он создаст третью таблицу в соответствии с тем, что предлагается здесь.
имеет значение в тех случаях, когда сначала добавляются отношения «чисто-многие-многие», а атрибуты создаются в БД позже.
Это не было сразу видно из этого потока / Googling. Так что просто поместите его там, так как это ссылка № 1 в Google, которая ищет проблему, но, прежде всего, из стороны БД.
@Esteban, код, который вы указали, прав, спасибо, но неполный, я его протестировал. В классе «UserEmail» отсутствуют свойства:
public UserTest UserTest { get; set; }
public EmailTest EmailTest { get; set; }
Я отправляю код, который я тестировал, если кто-то заинтересован. С уважением
using System.Data.Entity;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;
#region example2
public class UserTest
{
public int UserTestID { get; set; }
public string UserTestname { get; set; }
public string Password { get; set; }
public ICollection<UserTestEmailTest> UserTestEmailTests { get; set; }
public static void DoSomeTest(ApplicationDbContext context)
{
for (int i = 0; i < 5; i++)
{
var user = context.UserTest.Add(new UserTest() { UserTestname = "Test" + i });
var address = context.EmailTest.Add(new EmailTest() { Address = "address@" + i });
}
context.SaveChanges();
foreach (var user in context.UserTest.Include(t => t.UserTestEmailTests))
{
foreach (var address in context.EmailTest)
{
user.UserTestEmailTests.Add(new UserTestEmailTest() { UserTest = user, EmailTest = address, n1 = user.UserTestID, n2 = address.EmailTestID });
}
}
context.SaveChanges();
}
}
public class EmailTest
{
public int EmailTestID { get; set; }
public string Address { get; set; }
public ICollection<UserTestEmailTest> UserTestEmailTests { get; set; }
}
public class UserTestEmailTest
{
public int UserTestID { get; set; }
public UserTest UserTest { get; set; }
public int EmailTestID { get; set; }
public EmailTest EmailTest { get; set; }
public int n1 { get; set; }
public int n2 { get; set; }
//Call this code from ApplicationDbContext.ConfigureMapping
//and add this lines as well:
//public System.Data.Entity.DbSet<yournamespace.UserTest> UserTest { get; set; }
//public System.Data.Entity.DbSet<yournamespace.EmailTest> EmailTest { get; set; }
internal static void RelateFluent(System.Data.Entity.DbModelBuilder builder)
{
// Primary keys
builder.Entity<UserTest>().HasKey(q => q.UserTestID);
builder.Entity<EmailTest>().HasKey(q => q.EmailTestID);
builder.Entity<UserTestEmailTest>().HasKey(q =>
new
{
q.UserTestID,
q.EmailTestID
});
// Relationships
builder.Entity<UserTestEmailTest>()
.HasRequired(t => t.EmailTest)
.WithMany(t => t.UserTestEmailTests)
.HasForeignKey(t => t.EmailTestID);
builder.Entity<UserTestEmailTest>()
.HasRequired(t => t.UserTest)
.WithMany(t => t.UserTestEmailTests)
.HasForeignKey(t => t.UserTestID);
}
}
#endregion
Я хочу предложить решение, в котором могут быть достигнуты оба варианта конфигурации «многие-ко-многим».
«catch» - нам нужно создать представление, которое нацелено на таблицу объединения, поскольку EF проверяет, что таблица схемы может отображаться не более одного раза за EntitySet
.
ответ добавляет к тому, что уже было сказано в предыдущих ответах, и не отменяет ни один из этих подходов, он основывается на них.
Модель:
public class Member
{
public int MemberID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<MemberCommentView> MemberComments { get; set; }
}
public class Comment
{
public int CommentID { get; set; }
public string Message { get; set; }
public virtual ICollection<Member> Members { get; set; }
public virtual ICollection<MemberCommentView> MemberComments { get; set; }
}
public class MemberCommentView
{
public int MemberID { get; set; }
public int CommentID { get; set; }
public int Something { get; set; }
public string SomethingElse { get; set; }
public virtual Member Member { get; set; }
public virtual Comment Comment { get; set; }
}
Конфигурация:
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration;
public class MemberConfiguration : EntityTypeConfiguration<Member>
{
public MemberConfiguration()
{
HasKey(x => x.MemberID);
Property(x => x.MemberID).HasColumnType("int").IsRequired();
Property(x => x.FirstName).HasColumnType("varchar(512)");
Property(x => x.LastName).HasColumnType("varchar(512)")
// configure many-to-many through internal EF EntitySet
HasMany(s => s.Comments)
.WithMany(c => c.Members)
.Map(cs =>
{
cs.ToTable("MemberComment");
cs.MapLeftKey("MemberID");
cs.MapRightKey("CommentID");
});
}
}
public class CommentConfiguration : EntityTypeConfiguration<Comment>
{
public CommentConfiguration()
{
HasKey(x => x.CommentID);
Property(x => x.CommentID).HasColumnType("int").IsRequired();
Property(x => x.Message).HasColumnType("varchar(max)");
}
}
public class MemberCommentViewConfiguration : EntityTypeConfiguration<MemberCommentView>
{
public MemberCommentViewConfiguration()
{
ToTable("MemberCommentView");
HasKey(x => new { x.MemberID, x.CommentID });
Property(x => x.MemberID).HasColumnType("int").IsRequired();
Property(x => x.CommentID).HasColumnType("int").IsRequired();
Property(x => x.Something).HasColumnType("int");
Property(x => x.SomethingElse).HasColumnType("varchar(max)");
// configure one-to-many targeting the Join Table view
// making all of its properties available
HasRequired(a => a.Member).WithMany(b => b.MemberComments);
HasRequired(a => a.Comment).WithMany(b => b.MemberComments);
}
}
Контекст:
using System.Data.Entity;
public class MyContext : DbContext
{
public DbSet<Member> Members { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<MemberCommentView> MemberComments { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new MemberConfiguration());
modelBuilder.Configurations.Add(new CommentConfiguration());
modelBuilder.Configurations.Add(new MemberCommentViewConfiguration());
OnModelCreatingPartial(modelBuilder);
}
}
Из альбома Saluma (@ Saluma) answer
Если вы сейчас хотите найти все комментарии членов с LastName = «Смит», например, вы можете написать такой запрос:
blockquote>Это все еще работает ...
var commentsOfMembers = context.Members .Where(m => m.LastName == "Smith") .SelectMany(m => m.MemberComments.Select(mc => mc.Comment)) .ToList();
... но теперь также может быть ...
var commentsOfMembers = context.Members .Where(m => m.LastName == "Smith") .SelectMany(m => m.Comments) .ToList();
Или создать список членов с именем «Смит» (мы предполагаем, что их более одного) вместе с их комментариями можно использовать проекцию:
blockquote>Это все еще работает ...
var membersWithComments = context.Members .Where(m => m.LastName == "Smith") .Select(m => new { Member = m, Comments = m.MemberComments.Select(mc => mc.Comment) }) .ToList();
... но теперь также может быть ...
var membersWithComments = context.Members .Where(m => m.LastName == "Smith") .Select(m => new { Member = m, m.Comments }) .ToList();
Если вы хотите удалить комментарий от пользователя
var comment = ... // assume comment from member John Smith var member = ... // assume member John Smith member.Comments.Remove(comment);
Если вы хотите
Include()
комментарии участникаvar member = context.Members .Where(m => m.FirstName == "John", m.LastName == "Smith") .Include(m => m.Comments);
Все это похоже на синтаксический сахар, однако он дает вам несколько преимуществ, если вы захотите пройти дополнительную настройку. В любом случае, вы, похоже, сможете получить лучшее из обоих подходов.
Отличный ответ Slauma.
Я просто отправлю код, чтобы сделать это, используя свободное API отображение.
public class User {
public int UserID { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public ICollection<UserEmail> UserEmails { get; set; }
}
public class Email {
public int EmailID { get; set; }
public string Address { get; set; }
public ICollection<UserEmail> UserEmails { get; set; }
}
public class UserEmail {
public int UserID { get; set; }
public int EmailID { get; set; }
public bool IsPrimary { get; set; }
}
В вашем производном классе DbContext
вы можете сделать это:
public class MyContext : DbContext {
protected override void OnModelCreating(DbModelBuilder builder) {
// Primary keys
builder.Entity<User>().HasKey(q => q.UserID);
builder.Entity<Email>().HasKey(q => q.EmailID);
builder.Entity<UserEmail>().HasKey(q =>
new {
q.UserID, q.EmailID
});
// Relationships
builder.Entity<UserEmail>()
.HasRequired(t => t.Email)
.WithMany(t => t.UserEmails)
.HasForeignKey(t => t.EmailID)
builder.Entity<UserEmail>()
.HasRequired(t => t.User)
.WithMany(t => t.UserEmails)
.HasForeignKey(t => t.UserID)
}
}
Он имеет тот же эффект, что и принятый ответ, с другим подходом, который не лучше и не хуже.
EDIT: я изменил CreateDate с bool на DateTime.
EDIT 2: Из-за нехватки времени я разместил пример из приложения, над которым я работаю, чтобы быть уверенным это работает.
In your classes you can easily describe a many to many relationship with properties that point to each other.
, взятый из: msdn.microsoft.com/en-us/data/hh134698.aspx . Джулия Лерман не может ошибаться.
– Esteban
30 May 2013 в 03:55
Comments
в Member
. И вы не можете просто исправить это, переименовав вызов HasMany
в MemberComments
, потому что объект MemberComment
не имеет обратную коллекцию для WithMany
. На самом деле вам нужно настроить два отношения «один ко многим» , чтобы получить правильное отображение.
– Slauma
7 October 2013 в 12:38
OnModelCreating
. В этом примере используются только условные обозначения и аннотации данных. – Slauma 10 September 2012 в 22:08MemberId
иCommentId
, а не дополнительный третий столбецMember_CommentId
(или что-то в этом роде) - который означает, что у вас не было точных совпадающих имен между объектами для ваших ключей – Simon_Weaver 11 May 2013 в 06:17